Quantillon Protocol

Quantillon Protocol Smart Contracts

Production update, 17 October 2026: Signed Quotes in Production. Signed execution is active on Base; the periodic publisher is retired and the emergency-redemption budget is zero.

Current production behavior and settings: Production Protocol Reference.

Base deployment addresses and active versions (17 October 2026): Deployment guide · API address reference.

License: MIT Solidity Foundry Tests Security Security

Euro-pegged stablecoin protocol with dual-pool architecture, yield generation, and governance mechanisms

📖 Overview

Quantillon Protocol is a comprehensive DeFi ecosystem built around QEURO, a Euro-pegged stablecoin. The protocol features a dual-pool architecture that separates user deposits from hedging operations, enabling efficient yield generation while maintaining stability. The codebase ships an extensive Foundry test suite (unit, fuzz, integration, invariants), custom errors and centralized validation libraries, and role-based access control.

📚 Documentation

🎯 Key Features

  • Euro-Pegged Stablecoin: QEURO maintains 1:1 peg with Euro through sophisticated mechanisms
  • Dual-Pool Architecture: Separates user deposits from hedging operations for optimal risk management
  • Yield Generation: Multiple yield sources including protocol fees, interest differentials, and yield farming
  • Governance Token: QTI token with vote-escrow mechanics for decentralized governance (not yet activated — token supply not minted, governance dormant until launch)
  • Advanced Hedging: EUR/USD hedging positions with margin management and liquidation systems
  • Yield-Bearing Wrapper: stQEURO token that automatically accrues yield for holders
  • External Adapter Integration: Multi-vault adapter model with post-deploy onboarding
  • Comprehensive Security: Role-based access control, reentrancy protection, and emergency pause mechanisms
  • Gas-Optimized Design: Custom errors, centralized validation, and consolidated error libraries

🏗️ Architecture

Core Contracts

ContractPurposeKey Features
QEUROTokenEuro-pegged stablecoinMint/burn controls, rate limiting, compliance features, 18 decimals
QTITokenGovernance tokenVote-escrow mechanics, 100M supply cap, lock periods, 4× voting power. Governance dormant: no mint path is wired yet, so supply is 0 and lock/vote/propose are inactive until a future activation upgrade mints the cap.
QuantillonVaultMain vaultOvercollateralized minting (governance-set floor: 105% at launch, 102.5% under the September 2026 margin policy), liquidation mode at 101%, fee management
FeeCollectorFee distribution60/25/15 split to treasury/dev/community, per-token accounting
UserPoolUser depositsUSDC deposits, QEURO staking, unstaking cooldown; user yield accrues via stQEURO (no staking-reward claim)
HedgerPoolHedging operationsEUR/USD short positions, margin management, liquidation at 101% CR
stQEUROFactoryMulti-vault staking factoryDeploys one stQEURO proxy per vault, registry by vaultId
stQEUROTokenYield-bearing wrapperAutomatic yield accrual via exchange rate, no lock-up
MetaMorphoStakingVaultAdapterLive external vault adapterNon-upgradeable IExternalStakingVault adapter over the MetaMorpho USDC vault on Base (vaultId 2); AaveStakingVaultAdapter / MorphoStakingVaultAdapter wrap mock vaults for localhost
YieldShiftYield managementDynamic distribution between pools, 7-day holding period; allocation uses holding-period-filtered eligible-pool sizes with gradual adjustment (TWAP helpers exist but inform historical metrics, not the binding shift)
OracleRouterOracle routingSingle price entry point with two switchable slots; slot 1 currently hosts HyperliquidEurUsdOracle (active), slot 0 ChainlinkOracle (fallback)
HyperliquidEurUsdOracleActive EUR/USD oracleSigned reference valuation via SignedReferenceSource; independent-reference, freshness and circuit-breaker checks
ChainlinkOracleFallback price feedsEUR/USD (2 h staleness) and USDC/USD (25 h staleness) via Chainlink, circuit breakers
StorkOracleStork price feeds (parked)EUR/USD and USDC/USD via Stork Network; replaced in the router slot by HyperliquidEurUsdOracle
SignedExecutionPricingExact executionTransaction-bound quotes, expiry, nonce and hedge-capacity validation
SignedReferenceSourceReference valuationAuthenticated reports delivered with transactions and independently checked
SlippageStorageLegacy price storeRetained deployment; no longer the active market source
LighterEurUsdOracleInert oracle (historical)Deployed 2026-07-17 for a second hedge venue that was not adopted (2026-09-01); no router slot
TimeProviderTime utilitiesCentralized block.timestamp wrapper for consistent time management

🚀 Quick Start

Prerequisites

1. Clone and Setup

git clone https://github.com/Quantillon-Labs/smart-contracts.git
cd smart-contracts/quantillon-protocol
npm install

Note: scripts/deployment/ (deployment and upgrade scripts), the .env* templates and CLAUDE.private.md are git-crypt encrypted; the rest of scripts/ is plaintext so CI can run it. Building and testing does not need the key — contact the maintainers only if you need the deployment tooling.

2. Environment Configuration

# Copy an environment template for your target network
cp .env.localhost .env        # for local Anvil development
cp .env.base-sepolia .env     # for Base Sepolia testnet
cp .env.base .env             # for Base mainnet

3. Build and Test

# Build contracts
make build

# Run tests
make test

# Run security analysis
make slither

Testing conventions: Run make test before pushing; run make ci for full checks (build, test, Slither, NatSpec, gas and size analysis). CI (GitHub Actions, .github/workflows/quantillon-protocol-tests.yml at the repository root) splits all test files across four runners on push and pull requests to main. Reproduce one shard with bash scripts/ci-test-shard.sh 0 4 (indices 0–3); each uses the normal test profile and fuzz/invariant settings. The gating job requires every shard to pass, then runs make build and the upgrade-safety gate (make analyze-contract-sizes check-storage-layout check-abi check-version-bump). Nightly and manually dispatched runs execute the same four shards with --gas-report, then run make ci-base using the combined reports through FORGE_GAS_REPORT_FILE; the analysis job requires all shards to pass and does not rerun the full test suite. Reproduce a gas-report shard with bash scripts/ci-test-shard.sh 0 4 --gas-report. Use test_*, testFuzz_*, and invariant_* naming; avoid new assertTrue(true, ...) placeholders—convert or explicitly skip with rationale. See the test/ directory for test structure and coverage.

🚀 Deployment

🔐 Unified Deployment

Core contracts are deployed in a single forge script invocation via DeployQuantillon.s.sol. Deployed addresses are written to deployments/{chainId}/addresses.json.

# Deploy to localhost with mock contracts
./scripts/deployment/deploy.sh localhost --with-mocks

# Deploy to Base Sepolia testnet
./scripts/deployment/deploy.sh base-sepolia --verify

# Deploy to Base mainnet (production)
./scripts/deployment/deploy.sh base --verify --production

# Then onboard external vault adapters (post-core step)
./scripts/deployment/setup-external-vaults.sh --help

📋 Deployment Options

EnvironmentCommandDescription
localhost./scripts/deployment/deploy.sh localhost --with-mocksDevelopment with all mock contracts
localhost./scripts/deployment/deploy.sh localhost --with-mock-usdcDevelopment with MockUSDC, real Chainlink feeds
localhost./scripts/deployment/deploy.sh localhost --with-mock-oracleDevelopment with Mock Oracle, real USDC
localhost./scripts/deployment/deploy.sh localhostDevelopment with no mocks (real contracts)
base-sepolia./scripts/deployment/deploy.sh base-sepolia --verifyTestnet deployment with contract verification
base./scripts/deployment/deploy.sh base --verifyProduction deployment with verification

🔧 Deployment Features

  • 🔐 Secure Environment Variables: .env* templates are tracked git-crypt encrypted — never commit them in plaintext
  • 🌐 Multi-Network Support: Localhost (31337), Base Sepolia (84532), Base Mainnet (8453)
  • 🎭 Granular Mock Control: Choose which contracts to mock (--with-mocks, --with-mock-usdc, --with-mock-oracle)
  • ✅ Contract Verification: Automatic verification on block explorers via --verify
  • 🧪 Dry-Run Capability: Test deployments without broadcasting via --dry-run
  • ⚡ Smart Caching: Compilation cache preserved by default for faster deployments (use --clean-cache to force full rebuild)
  • 📝 Post-Deployment Tasks: Automatic ABI copying and address updates

🛡️ Security Features

  • Environment Variables: .env* templates are tracked git-crypt encrypted — never commit them in plaintext, never disable the filter
  • Secret Management: Prefer a secret manager for production (e.g., AWS Secrets Manager)

🧪 Testing

Run All Tests

make test

Run Specific Test Suites

# Core protocol tests
forge test --match-contract QuantillonVault

# Integration tests
forge test --match-contract IntegrationTests

# Reentrancy and security-oriented tests
forge test --match-contract ReentrancyTests

Gas Analysis

make gas-analysis

🔍 Security

Automated Security Analysis

# Run Slither static analysis
make slither

# Run Mythril analysis
make mythril

# Validate NatSpec documentation
make validate-natspec

# Check contract bytecode size limits (EIP-170)
make analyze-contract-sizes

# Enforce a personal EIP-170 budget (example: 97%)
EIP170_PERSONAL_LIMIT_PERCENT=97 make analyze-contract-sizes

Security And Quality Reports

Analysis outputs are written under scripts/results/:

  • scripts/results/slither/slither-report.txt - Slither executive summary and unresolved/suppressed/excluded sections
  • scripts/results/mythril-reports/ - Mythril per-contract JSON and timestamped text summaries
  • scripts/results/natspec-validation-report.txt - NatSpec validation coverage report
  • scripts/results/contract-sizes/contract-sizes-summary.txt - EIP-170 size compliance summary
  • scripts/results/gas-analysis/ - Gas analysis outputs

Security Features

  • Role-Based Access Control: Granular permissions for different operations
  • Reentrancy Protection: Comprehensive reentrancy guards
  • Emergency Pause: Circuit breakers for critical functions
  • Input Validation: Extensive parameter validation with centralized libraries
  • Overflow Protection: Safe math operations throughout
  • Flash Loan Protection: Balance checks to prevent flash loan attacks
  • Custom Errors: Gas-efficient error handling with clear error messages
  • Secret Handling: Environment variables loaded from .env during development
  • 🔐 Encrypted Paths: scripts/deployment/, .env* and CLAUDE.private.md are git-crypt encrypted (see .gitattributes); everything else is plaintext

📊 Development

Available Commands

# Build contracts
make build

# Run tests
make test

# Run security analysis
make slither

# Generate documentation
make docs

# Clean build artifacts
make clean

# Gas analysis
make gas-analysis

Code Quality

  • NatSpec Documentation: Comprehensive documentation for all functions
  • Test Coverage: Extensive test suite (unit, fuzz, integration, invariants) — make test
  • Security Analysis: Regular security audits and static analysis
  • Gas Optimization: Optimized for deployment size and execution cost
  • Error Handling: Custom errors for gas efficiency and better error messages
  • Code Deduplication: Consolidated validation functions and error libraries
  • Stack Optimization: Fixed stack too deep issues through struct-based refactoring

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Guidelines

  • Follow Solidity style guide
  • Write comprehensive tests (aim for 100% coverage)
  • Update documentation
  • Ensure security best practices
  • Protect secrets: .env* files are tracked but git-crypt encrypted — never commit them in plaintext, never disable the filter
  • Use custom errors instead of require() strings for gas efficiency
  • Consolidate duplicate code into libraries
  • Follow the centralized error library pattern (CommonErrorLibrary)

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • OpenZeppelin for secure contract libraries
  • Chainlink for reliable price feeds
  • Morpho (MetaMorpho vaults) for the live external yield venue and Hyperliquid for the hedge venue and EUR/USD market price
  • Foundry for development framework
  • Standard .env files for environment variable management

Yield crediting uses an independent solvency gate above max(101%, criticalCollateralizationRatio) and a projected 100% floor; public minting continues to use the live configured mint floor.

Staking yield distribution 1.5.0

Production QuantillonVault 1.5.0 was activated on 30 September 2026. Vault 1.6.0, activated on 17 October, preserves that policy and allocates harvested yield by the staked/total QEURO ratio, with haircut-only hedger compensation and no separate staking yield fee. Yield credit vests through the share price; allocation remains snapshot-weighted. See the economics and confirmed activation record. The capital-weighted 1.4 guide is historical.

Production Deployment Status

Signed quotes are active on Base since 17 October 2026. Versions, signed-module bindings, oracle routing, zero mint/redemption fees, the 102.5% mint floor, the 101% critical threshold and zero QTI supply were rechecked at finalized Base block 52,727,379. The signed module is in NORMAL mode with an emergency budget of 0 QEURO. See Signed Quotes and the confirmed activation.

The broader parameter, role and availability review below was performed on 30 September 2026, using finalized Base block 51,985,907. Settings not listed in the October recheck retain that earlier verification date. These are dated observations, not immutable defaults; read current state and obtain a fresh quote before transacting.

Deployment and availability

Contracts are deployed on Base mainnet (8453). The public application is at app.quantillon.money; the public launch remains a Q4 2026 target, not a confirmed opening date. There is no Ethereum-mainnet deployment. Development and preproduction use separate Base forks; the former public testnet is retired.

QTI is deployed but has zero supply. Its vote-escrow and proposal machinery is dormant. Quantillon Rewards is deployed, but the public program state is off and enrollment is not open. QP points promise neither monetary value nor a token allocation.

User flows and backing

  • Users mint QEURO with USDC through QuantillonVault. Normal mint/redeem amounts use transaction-specific signed execution quotes, valid for at most 45 seconds from the market observation, including depth, spread and buffer constraints, rather than simply multiplying by the oracle mid. Zero protocol fees do not mean zero execution cost.
  • The dapp stakes QEURO directly into an ERC-4626 stQEURO series. The optional UserPool batch contract has separate accounting and a cooldown; these are not the direct stQEURO staking rules.
  • The current external strategy is the MetaMorpho USDC vault, registered as vaultId 2. QEURO backing can be deployed there; hedger margin is not part of its yield-bearing principal. External backing is counted conservatively, capped by tracked principal and current underlying value; the execution-spread reserve is excluded from backing.
  • Minting has a 102.5% collateralization floor, plus oracle, execution-capacity, token, pause and liquidity checks. Protocol liquidation mode applies when the computed ratio is positive and at or below 101%. A zero ratio is not an automatic liquidation signal. Redemptions remain subject to validation and available liquidity.

See Execution Pricing, Liquidation Mode and External Staking Vaults.

Yield and fees

SettingVerified value / meaning
Vault mint and redemption fee0; each configurable up to 5%
Morpho allocationHarvest-time staked-QEURO fraction to stakers; unstaked fraction to treasury
Hedger staking-yield haircut0 bps; no base allocation for hedger collateral
stQEURO vesting24 hours; allocation remains snapshot-weighted
Legacy stQEURO yield feeIgnored by the credit path introduced in vault 1.5.0 and preserved in 1.6.0
Vault hedgerRewardFeeSplit20% of collected vault fees routed to the hedger reward reserve; not a reward-claim tax
HedgerPool entry / exit / margin fees0
HedgerPool rewardFeeSplit0; separate routing setting for fees collected by HedgerPool
FeeCollector distribution60% treasury / 25% development / 15% community, for receipts reaching FeeCollector
Optional UserPool configuration8% staking / 4% deposit accounting APY; minimum stake 100 QEURO; 7-day cooldown; performance fee 0

UserPool's configured accounting rates are not Morpho's realized return or the direct stQEURO APY. The displayed Morpho rate is an underlying provider metric, not a guaranteed QEURO return. See Yield Distribution for the allocation formula and conversion costs. YieldShift remains a separate authorized-source ledger.

Hedge and oracle

The single designated hedger maintains a Base HedgerPool position and a Hyperliquid xyz:EUR position. HedgerPool's minimum margin is 2.5% and its configured maximum leverage is 40x. Configured EUR/USD annual interest inputs are 3.5% / 4.5%; they are not promises of realized hedger profit. Order preparation inside Hyperliquid and movement of capital between venues are distinct operations.

OracleRouter slot 1 uses HyperliquidEurUsdOracle; slot 0 is the manually selected Chainlink fallback. HyperliquidEurUsdOracle 1.0.7 reads SignedReferenceSource, which accepts authenticated reference reports delivered with transactions and checks an independent Chainlink reference. The periodic publisher is retired. A stale reference can block operations even when the venue is trading. Switching to Chainlink does not by itself restore minting: execution pricing also checks source compatibility and admitted hedge capacity.

Governance and security

The governance Safe requires 2 of 3 signers. The 12-hour TimelockController holds DEFAULT_ADMIN_ROLE on the eight core contracts, including the stQEURO series. Core role grants and revocations therefore use that controller. The Safe retains direct operational, governance and emergency permissions according to each contract's roles; it holds the peripheral admin roles.

Core upgrades use the timelock while secure upgrades are enabled. SecureUpgradeable also contains a separate emergency-disable procedure with a 24-hour delay and two distinct admin approvals; it is not an ordinary pause operation. Peripheral upgrades can be executed directly by the Safe. See Quantillon DAO for the control boundaries.

No professional security audit has been performed. Review to date is internal and AI-assisted. This does not establish that the contracts are free of defects. See Risks and Mitigation.

Token guardrails and references

QEURO has an adjustable administrative supply ceiling of 100 million, and global mint and burn limits of 10 million per 300-block window. These are controls, not a fixed tokenomic issuance promise. Whitelist mode and the minting killswitch were off at the verification block.

The contract inventory records addresses and versions. Core Mechanisms explains the flows. The roadmap and planned QTI allocations describe future intentions, not current issuance or guaranteed dates.

Evidence and maintenance

This reference describes the current deployment, not an audit certification. The broader settings and role review used finalized Base block 51,985,907; the October versions and signed bindings listed above were independently read at finalized block 52,727,379. User flows were checked against contract source and deployed ABIs. Runtime routing and Rewards availability were checked separately on 30 September 2026. Future launch, distribution and entity plans remain organizational intentions.

Deployment manifests record upgrade history and can lag live state; use version(), role reads and the active vault bindings for current integration. Do not infer the active implementation from a historical release section alone.

Quantillon Protocol API Reference

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

Technical API Reference

This document provides detailed technical specifications for all Quantillon Protocol smart contract interfaces.


Contract Addresses

Deployed addresses for Base Mainnet (chain ID 8453). The machine-readable registry deployments/8453/addresses.json is a local deployment artifact (gitignored, not published); the tracked deployments/8453/versions.json carries the proxy and implementation address plus versions recorded by deployment tooling; these records can lag subsequent upgrades, so read live version() values. All core contracts are UUPS proxies — the addresses below are the stable proxy addresses that integrators should use.

Core protocol

ContractAddress
QuantillonVault0x833E5Ba510a241b21F1C60c987D1c49eB52E4a07
QEUROToken0x69aD4e6c49d6275D0e11b5515D98a89f029869AA
QTIToken0x246c6F441c0f8Fc6A71Db0F12dB5665D373Df271
UserPool0x712bCc77e7aa53C79870A40d044D440Ad2901bF2
HedgerPool0xff5D7cE5c7671B2EA805Ee752B4f8eC9Ecf2975A
FeeCollector0x0A33F72683cfC2303639d5cB9A45D77fF16d9FAD
YieldShift0xdcd66568F8623bDa3387287c31F14b43e49665b1
stQEUROFactory0x0382B0b9FB6Ff737209C3B31D727BB9d2E2bcb53
stQEUROTokenper-vault — deployed by stQEUROFactory, resolve via getStQEUROByVaultId(vaultId)

Oracles

ContractAddressStatus
OracleRouter0x7ED6aaEd83Db69509A88CAe5C247ef8fA44056E0entry point for all protocol price reads
HyperliquidEurUsdOracle0x0B58aBB57775E0fCEDfd4460e00dD9D9610C2C43ACTIVE (router slot 1)
ChainlinkOracle0xaEE3c9c298051ef7242882AbCaE2Fd12d29443E7fallback (router slot 0); USDC/USD source
StorkOracle0x41FcE00E33Ca4f0d8E5528c343FAC98BA178EebCparked (replaced in slot 1 by HyperliquidEurUsdOracle)
LighterEurUsdOracle0xcd53182a430d48Be0f414CCA022ABA5d05903536deployed 2026-07-17, inert: holds no router slot and the Lighter venue was not adopted (decision of 2026-09-01)
SlippageStorage0x0fde0ff2566be3c24af6d654012dddb4f1da099blegacy price store; not the active signed reference source
TimeProvider0x520236487CBD0a6958B4EefC7853cd7C3F5C56E7timestamp wrapper (deployed directly, not proxied)

Protocol contracts depend only on OracleRouter (which implements IOracle). The router has two slots — enum OracleType { CHAINLINK, MARKET } (slot 1 was named STORK before router v1.1.0; the live router is v1.1.2) — switchable in one governance transaction via switchOracle. Slot 1 currently hosts HyperliquidEurUsdOracle, the active production oracle (activeOracle = 1); read it via marketOracle() (the pre-1.1.0 storkOracle() getter remains as a deprecated alias). Slot 0 (ChainlinkOracle) is the fallback and remains the USDC/USD source.

Signed execution and reference (Base, 17 October 2026)

Verified at finalized block 52,727,379. Both modules are deployed directly and are non-upgradeable. Resolve QuantillonVault.executionPricing() and the module's referenceSource() before integration.

ContractAddressVersion / role
SignedExecutionPricing0x076F86a591258957665b65c04F04B706D00EaEBa1.1.0; active signed execution
SignedReferenceSource0xFd059ed44959a6a7979e1485a825CE36Dc95cCB11.0.0; active signed valuation source

QuantillonVault is 1.6.0, UserPool 1.3.0, HedgerPool 1.6.0, HyperliquidEurUsdOracle 1.0.7 and vaultId-2 stQEUROToken 1.3.0. The production integration guide records the activation and binding checks.

Normal conversions use QuantillonVault.executeWithQuote(bytes,bytes) or UserPool.executeWithQuote(bytes,bytes). Existing conversion selectors below describe the inner operations; bare unquoted calls are rejected while signed execution is enabled. Hedger reference operations use executeWithReference(bytes,bytes) or the typed removeMarginWithReference(uint256,uint256,bytes) and retain caller permissions. Add-margin remains directly available to authorized callers.

The previous ExecutionPricing module (0x4338c6C9A912d51487cc0bf3b20162fdb25eFc03), PublicationBatcher (0x0E7a3df68D527249fB3A2e66dC307ed1F119172d) and ReportPublicationBatcher (0x2efA498B9Fa9903A371A9fbE561555AD10589EeA) are historical. The periodic publication route is retired.

Governance & infrastructure

ContractAddressNotes
Gnosis Safe (governance)0x1d7fF432a93d0085Fb69474c7E567f859829e6cd2-of-3 governance; core default-admin authority belongs to the controller
TimelockController0x7Ade8f3Bf1FdaF0785efE9Ea5C6339D1aD6B8342OpenZeppelin TimelockController, 12 h delay, Safe = sole proposer/executor. Gates upgrades and default-admin operations of the eight SecureUpgradeable proxies (QuantillonVault, QEUROToken, QTIToken, UserPool, HedgerPool, YieldShift, stQEUROFactory, per-vault stQEUROToken). FeeCollector, OracleRouter, ChainlinkOracle, HyperliquidEurUsdOracle, LighterEurUsdOracle (inert), StorkOracle and SlippageStorage are plain UUPS proxies whose upgrade role is held by the Safe: they upgrade in a single Safe transaction, with no timelock

External vault adapters (onboarded post-core)

External staking adapters are onboarded after core deployment via setup-external-vaults.sh and are tracked per vaultId, not in addresses.json. Currently live:

AdapterAddressvaultId
MetaMorphoStakingVaultAdapter0x4c9B8b09214d37D5310b8E6768cF28E0dDcEDC302

The previous vaultId-2 adapter (0xb2f253Cd74ebfa16894339438B467396De9e8EA3) was migrated to the version-2.1.1 address above on 2026-09-23. Per-vault adapter records (deployments/8453/*-adapter.json) are local deployment artifacts and are not tracked in this repository; the live binding is readable on-chain via QuantillonVault.getVaultExposure(2).

Per-vault stQEURO tokens

addresses.json intentionally lists stQEUROToken as the zero address: stQEURO is deployed per external vault by stQEUROFactory and must be resolved at runtime via getStQEUROByVaultId(vaultId). Currently live:

VaultvaultIdstQEURO proxyUnderlying vault
MORPHO1 (MetaMorpho)20x17CD8ed967d17072297CcAe3D379C9e86aeBEb1d0xBEEFE94c8aD530842bfE7d8B397938fFc1cb83b2

External dependencies

Token / FeedAddress
USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Chainlink EUR/USD feed0xc91D87E81faB8f93699ECf7Ee9B44D11e1D53F0F
Chainlink USDC/USD feed0x7e860098F58bBFC8648a4311b374B1D669a2bc6B

QuantillonVault

Contract: QuantillonVault.sol
Interface: IQuantillonVault.sol
Inherits: SecureUpgradeable, PausableUpgradeable

Function Signatures

initialize(address admin, address _qeuro, address _usdc, address _oracle, address _hedgerPool, address _userPool, address _timelock, address _feeCollector)

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _oracle,
    address _hedgerPool,
    address _userPool,
    address _timelock,
    address _feeCollector
) external

Modifiers: initializer
Notes:

  • _hedgerPool and _userPool can be wired later through governance setters.
  • _timelock is also used as treasury destination for recovery flows.

mintQEURO(uint256 usdcAmount, uint256 minQeuroOut)

function mintQEURO(
    uint256 usdcAmount,
    uint256 minQeuroOut
) external

Modifiers: whenNotPaused, nonReentrant
Events: QEUROminted(address indexed user, uint256 usdcAmount, uint256 qeuroAmount)
Requirements:

  • usdcAmount > 0
  • Price cache initialized (initializePriceCache)
  • Active hedger configured (hedgerPool.hasActiveHedger())
  • Sufficient USDC balance and allowance
  • Projected post-mint collateralization ratio must remain above threshold

redeemQEURO(uint256 qeuroAmount, uint256 minUsdcOut)

function redeemQEURO(
    uint256 qeuroAmount,
    uint256 minUsdcOut
) external

Modifiers: whenNotPaused, nonReentrant
Events: QEURORedeemed(address indexed user, uint256 qeuroAmount, uint256 usdcAmount)
Requirements:

  • qeuroAmount > 0
  • Sufficient QEURO balance and allowance
  • Automatically routes to liquidation mode when protocol CR is positive and at or below the critical threshold
  • Pulls liquidity from external vault adapters when needed (tracked principal only; unharvested adapter yield is not used as redemption collateral)

Execution previews

The former calculateMintAmount and calculateRedeemAmount helpers are absent from the current vault ABI. Resolve vault.executionPricing() and use ExecutionPricing.previewMint(usdcInput) or previewRedeem(qeuroInput) for normal execution.

Both return a Quote tuple: amountOut, executionRate, referenceRate, capacityQeuro, observedAt, sequence (all uint256). Mint output is QEURO in 18 decimals; redeem output is USDC in 6 decimals. Preview outputs include the configured protocol fee. Prices are 18-decimal USD/EUR and capacity is 18-decimal QEURO. Quotes can revert and do not reserve capacity.

The redemption preview can use the module's degraded quote path. It is not a liquidation-mode payout preview. Simulate the actual vault call with a user-selected minimum output and the user's account before submitting. See Integration Examples.

Vault balance getters (public state)

uint256 public totalUsdcHeld;              // USDC held directly by the vault
uint256 public totalMinted;                // QEURO minted by vault tracker
uint256 public totalUsdcInExternalVaults;  // Principal tracked across external vault adapters

Notes:

  • The aggregated getVaultMetrics() helper was retired in the external multi-vault refactor (EIP-170 headroom); read the three public trackers directly, and use getProtocolCollateralizationRatio() for debt/collateral ratio math (1e20 = 100%). Do not sum the trackers as proof of redeemable backing: external strategy losses and the excluded execution-spread reserve matter. Use getTotalUsdcAvailable() and the collateralization getter; unharvested yield is not backing.

getProtocolCollateralizationRatio() → (uint256)

function getProtocolCollateralizationRatio() public view returns (uint256 ratio)

Returns: Current protocol collateralization ratio in 18-decimal percentage format (100% = 1e20)

Description: Calculates CR = (TotalCollateral / BackingRequirement) * 1e20 where:

  • TotalCollateral = totalUsdcHeld + tracked external-vault principal (unharvested adapter yield is excluded; it accrues to stQEURO holders via harvestAndDistributeVaultYield/creditVaultYield)
  • BackingRequirement = QEUROSupply * cachedEurUsdPrice / 1e30

Note: This function uses cached price and returns 0 when required wiring/cache prerequisites are not met.

Requirements:

  • Both HedgerPool and UserPool must be set
  • Initialized cached price
  • QEURO supply > 0

canMint() → (bool)

function canMint() public view returns (bool)

Returns: true if minting is allowed, false otherwise

Description: Checks if minting is allowed under current safeguards:

  • Cached price must be initialized.
  • Active hedger must exist.
  • Collateralization ratio must be >= minCollateralizationRatioForMinting.

initializePriceCache()

Governance-only bootstrap step required after deployment and before first user mint.

updateHedgerRewardFeeSplit(uint256 newSplit)

Governance setter for fee routing share to HedgerPool reserve (1e18 = 100%).

mintQEUROToVault(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId)

User entrypoint for minting QEURO and routing collateral to a specific external vault adapter.

mintAndStakeQEURO(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId, uint256 minStQEUROOut) → (uint256 qeuroMinted, uint256 stQEUROMinted)

One-step user entrypoint to mint QEURO and stake into the vault-specific stQEURO token.

deployUsdcToVault(uint256 vaultId, uint256 usdcAmount)

Vault-operator entrypoint for manual collateral deployment to a specific adapter.

harvestAndDistributeVaultYield(uint256 vaultId)

Keeper entrypoint (YIELD_DISTRIBUTOR_ROLE). In live vault 1.5.0, gross staker yield is harvested USDC multiplied by the harvest-time ratio of raw staked QEURO to total QEURO supply. Stakers receive that allocation after the configured haircut; treasury receives the unstaked allocation; the hedger receives only the haircut (currently zero). Conversion execution costs remain. Emits VaultYieldDistributed(vaultId, realizedYield, hedgerShare, userShare, treasuryShare) and VaultYieldBreakdown with hedgerBase = 0. See the 1.5.0 distribution guide.

creditVaultYield(uint256 vaultId, uint256 usdcAmount) → (uint256 qeuroMinted)

YIELD_DISTRIBUTOR_ROLE entrypoint crediting externally realized USDC yield into a vault's stQEURO backing.

harvestConfig(uint256 vaultId) → (uint256 fundingRateBps, address hedgerRecipient, uint256 lastHarvest)

Compatibility view: the retired funding-rate result is always zero. Use yieldDistributionConfig(vaultId) for (haircutBps, hedgerRecipient, lastHarvest).

setFundingRateAnnualBps(uint256 newRateBps) / setHedgerYieldRecipient(address newRecipient)

setFundingRateAnnualBps is retired and reverts. Governance configures the haircut with setHedgerStakingYieldHaircutBps(uint256 newBps) (0–10,000 bps), and its recipient with setHedgerYieldRecipient. These emit HedgerStakingYieldHaircutUpdated and HedgerYieldRecipientUpdated.

Events

event QEUROminted(address indexed user, uint256 usdcAmount, uint256 qeuroAmount);
event QEURORedeemed(address indexed user, uint256 qeuroAmount, uint256 usdcAmount);
event LiquidationRedeemed(address indexed user, uint256 qeuroAmount, uint256 usdcPayout, uint256 collateralizationRatioBps, bool isPremium);
event ProtocolFeeRouted(string sourceType, uint256 totalFee, uint256 hedgerReserveShare, uint256 collectorShare);
event StakingVaultConfigured(uint256 indexed vaultId, address indexed adapter, bool active);
event UsdcDeployedToExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalInVault);
event UsdcWithdrawnFromExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalInVault);
event VaultYieldDistributed(uint256 indexed vaultId, uint256 realizedYield, uint256 hedgerShare, uint256 userShare, uint256 treasuryShare);

QEUROToken

Contract: QEUROToken.sol
Interface: IQEUROToken.sol
Inherits: ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable (timelock-gated upgrades)

Function Signatures

mint(address to, uint256 amount)

function mint(address to, uint256 amount) external

Modifiers: onlyRole(MINTER_ROLE) (held by QuantillonVault), whenNotPaused Events: TokensMinted(address indexed to, uint256 indexed amount, address indexed minter) Requirements:

  • Minting killswitch off (mintingKillswitch() == false, else MintingDisabled)
  • amount > 0; to passes the compliance checks (BlacklistedAddress; NotWhitelisted while whitelist mode is on)
  • totalSupply() + amount <= maxSupply() (WouldExceedLimit)
  • Within the mint rate limit (rateLimitCaps().mint per 300-block window, else RateLimitExceeded)

burn(address from, uint256 amount)

function burn(address from, uint256 amount) external

Modifiers: onlyRole(BURNER_ROLE) (held by QuantillonVault), whenNotPaused Events: TokensBurned(address indexed from, uint256 indexed amount, address indexed burner) Requirements:

  • amount > 0 and balanceOf(from) >= amount
  • Within the burn rate limit (rateLimitCaps().burn per 300-block window, else RateLimitExceeded)

batchMint(address[] recipients, uint256[] amounts) / batchBurn(address[] froms, uint256[] amounts)

Batched variants of mint / burn (same roles and checks; at most MAX_BATCH_SIZE = 100 entries).

whitelistAddress(address account) / unwhitelistAddress(address account)

Modifiers: onlyRole(COMPLIANCE_ROLE) Events: AddressWhitelisted(address indexed account) / AddressUnwhitelisted(address indexed account)

blacklistAddress(address account, string reason) / unblacklistAddress(address account)

Modifiers: onlyRole(COMPLIANCE_ROLE) Events: AddressBlacklisted(address indexed account, string indexed reason) / AddressUnblacklisted(address indexed account)

Batched variants: batchWhitelistAddresses, batchUnwhitelistAddresses, batchBlacklistAddresses(address[] accounts, string[] reasons), batchUnblacklistAddresses (MAX_COMPLIANCE_BATCH_SIZE = 50). toggleWhitelistMode(bool enabled) (COMPLIANCE_ROLE) emits WhitelistModeToggled(bool enabled).

updateMaxSupply(uint256 newMaxSupply)

function updateMaxSupply(uint256 newMaxSupply) external

Modifiers: onlyRole(DEFAULT_ADMIN_ROLE) Events: SupplyCapUpdated(uint256 oldCap, uint256 newCap) Requirements: newMaxSupply >= totalSupply() (otherwise NewCapBelowCurrentSupply)

updateRateLimits(uint256 newMintLimit, uint256 newBurnLimit)

Modifiers: onlyRole(DEFAULT_ADMIN_ROLE) — each limit must be <= MAX_RATE_LIMIT (10M QEURO), else RateLimitTooHigh Events: RateLimitsUpdated(string indexed limitType, uint256 mintLimit, uint256 burnLimit)

setMintingKillswitch(bool enabled)

Modifiers: onlyRole(PAUSER_ROLE) Events: MintingKillswitchToggled(bool enabled, address indexed caller)

getTokenInfo() → (string, string, uint8, uint256, uint256, bool, bool, uint256, uint256)

function getTokenInfo() external view returns (
    string memory name_,
    string memory symbol_,
    uint8 decimals_,
    uint256 totalSupply_,
    uint256 maxSupply_,
    bool isPaused_,
    bool whitelistEnabled_,
    uint256 mintRateLimit_,
    uint256 burnRateLimit_
)

State getters

maxSupply(), getSupplyUtilization(), rateLimitCaps() → (uint128 mint, uint128 burn), mintRateLimit(), burnRateLimit(), rateLimitInfo() → (uint96 currentHourMinted, uint96 currentHourBurned, uint64 lastRateLimitReset), mintingKillswitch(), whitelistEnabled(), isWhitelisted(address), isBlacklisted(address), isMinter(address), isBurner(address).

Events

event TokensMinted(address indexed to, uint256 indexed amount, address indexed minter);
event TokensBurned(address indexed from, uint256 indexed amount, address indexed burner);
event AddressWhitelisted(address indexed account);
event AddressUnwhitelisted(address indexed account);
event AddressBlacklisted(address indexed account, string indexed reason);
event AddressUnblacklisted(address indexed account);
event WhitelistModeToggled(bool enabled);
event SupplyCapUpdated(uint256 oldCap, uint256 newCap);
event RateLimitsUpdated(string indexed limitType, uint256 mintLimit, uint256 burnLimit);
event RateLimitReset(uint256 indexed blockNumber);
event MintingKillswitchToggled(bool enabled, address indexed caller);

QTIToken

Contract: QTIToken.sol
Inherits: ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable (timelock-gated upgrades)

Function Signatures

lock(uint256 amount, uint256 lockTime) → (uint256)

function lock(uint256 amount, uint256 lockTime) external returns (uint256 veQTI)

Modifiers: whenNotPaused, nonReentrant
Events: TokensLocked(address indexed user, uint256 amount, uint256 lockTime, uint256 votingPower)
Requirements:

  • amount > 0
  • lockTime >= MIN_LOCK_TIME && lockTime <= MAX_LOCK_TIME
  • Sufficient QTI balance

unlock() → (uint256)

function unlock() external returns (uint256 amount)

Modifiers: whenNotPaused, nonReentrant
Events: TokensUnlocked(address indexed user, uint256 amount)
Requirements: Lock period has expired

getVotingPower(address user) → (uint256)

function getVotingPower(address user) external view returns (uint256 votingPower)

getLockInfo(address user) → (uint256, uint256, uint256, uint256)

function getLockInfo(address user) external view returns (
    uint256 lockedAmount,
    uint256 lockTime,
    uint256 unlockTime,
    uint256 currentVotingPower
)

createProposal(string memory description, uint256 startTime, uint256 endTime) → (uint256)

function createProposal(
    string memory description,
    uint256 startTime,
    uint256 endTime
) external returns (uint256 proposalId)

Modifiers: whenNotPaused
Events: ProposalCreated(uint256 indexed proposalId, string description, uint256 startTime, uint256 endTime)
Requirements:

  • Sufficient voting power
  • Valid time parameters

vote(uint256 proposalId, bool support)

function vote(uint256 proposalId, bool support) external

Modifiers: whenNotPaused
Events: VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 votingPower)
Requirements:

  • Voting period active
  • Sufficient voting power
  • Not already voted

Events

event TokensLocked(address indexed user, uint256 amount, uint256 lockTime, uint256 votingPower);
event TokensUnlocked(address indexed user, uint256 amount);
event ProposalCreated(uint256 indexed proposalId, string description, uint256 startTime, uint256 endTime);
event VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 votingPower);

UserPool

Contract: UserPool.sol Interface: IUserPool.sol Inherits: SecureUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable

Optional batch front-end over the vault: deposit mints QEURO through QuantillonVault.mintQEURO and sends it to the caller's wallet, withdraw pulls QEURO from the caller's wallet and redeems it through QuantillonVault.redeemQEURO, and stake / requestUnstake / unstake escrow QEURO behind a cooldown. User yield does not accrue here — it accrues through the per-vault stQEURO ERC-4626 token (see stQEUROToken); the former staking-reward claim path was removed. Every user-facing amount function takes arrays (use a one-element array for a single operation); batches are capped at MAX_BATCH_SIZE = 100.

Function Signatures

deposit(uint256[] usdcAmounts, uint256[] minQeuroOuts) → (uint256[] qeuroMintedAmounts)

function deposit(uint256[] calldata usdcAmounts, uint256[] calldata minQeuroOuts)
    external returns (uint256[] memory qeuroMintedAmounts)

Modifiers: nonReentrant, whenNotPaused Events: UserDeposit(address indexed user, uint256 usdcAmount, uint256 qeuroMinted, uint256 timestamp) and UserDepositTracked(...) per entry Requirements:

  • usdcAmounts.length == minQeuroOuts.length, non-empty, at most MAX_BATCH_SIZE (ArrayLengthMismatch / EmptyArray / BatchSizeTooLarge)
  • each usdcAmounts[i] > 0 (6 decimals); minQeuroOuts[i] is the per-entry slippage floor (18 decimals)
  • Sufficient USDC balance and allowance to the UserPool; the vault must accept the mint (QuantillonVault.canMint())

withdraw(uint256[] qeuroAmounts, uint256[] minUsdcOuts) → (uint256[] usdcReceivedAmounts)

function withdraw(uint256[] calldata qeuroAmounts, uint256[] calldata minUsdcOuts)
    external returns (uint256[] memory usdcReceivedAmounts)

Modifiers: nonReentrant, whenNotPaused Events: UserWithdrawal(address indexed user, uint256 qeuroBurned, uint256 usdcReceived, uint256 timestamp) and UserWithdrawalTracked(...) per entry; WithdrawalPending(user, amount) when the USDC transfer to the user fails (e.g. USDC blacklist) Requirements:

  • array lengths match, non-empty, at most MAX_BATCH_SIZE; each qeuroAmounts[i] > 0 (18 decimals)
  • Sufficient QEURO balance in the caller's wallet and allowance to the UserPool; minUsdcOuts[i] is the per-entry slippage floor (6 decimals)

claimPendingWithdrawal()

Pulls USDC that was queued in pendingUsdcWithdrawals(user) after a failed transfer during withdraw. nonReentrant, whenNotPaused; emits PendingWithdrawalClaimed(address indexed user, uint256 amount); reverts InsufficientBalance when nothing is pending.

stake(uint256[] qeuroAmounts)

function stake(uint256[] calldata qeuroAmounts) external

Modifiers: nonReentrant, whenNotPaused Events: QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 timestamp) per entry Requirements:

  • non-empty, at most MAX_BATCH_SIZE entries; each qeuroAmounts[i] >= minStakeAmount() (settable; 100 QEURO live)
  • Sufficient QEURO balance and allowance to the UserPool

requestUnstake(uint256 qeuroAmount)

function requestUnstake(uint256 qeuroAmount) external

Modifiers: nonReentrant Starts the unstaking cooldown (unstakingCooldown(), 7 days live) for qeuroAmount of the caller's staked balance; recorded in getUserInfo(user).unstakeAmount / .unstakeRequestTime.

unstake()

function unstake() external

Modifiers: nonReentrant, whenNotPaused Events: QEUROUnstaked(address indexed user, uint256 qeuroAmount, uint256 timestamp) Requirements: a pending requestUnstake whose cooldown has elapsed. Transfers the requested QEURO back to the caller.

getUserInfo(address user) → (uint256 × 7)

function getUserInfo(address user) external view returns (
    uint256 qeuroBalance,        // legacy field, never written: deposited QEURO goes to the user's wallet
    uint256 stakedAmount,        // QEURO currently staked (18 decimals)
    uint256 pendingRewards,      // always 0: the staking-reward path was removed
    uint256 depositHistory,      // cumulative USDC deposited (6 decimals)
    uint256 lastStakeTime,
    uint256 unstakeAmount,       // QEURO in a pending unstake request
    uint256 unstakeRequestTime
)

Pool views

function getPoolTotals() external view returns (uint256 totalDeposits, uint256 totalWithdrawals, uint256 totalStakes_, uint256 totalUsers_);
function getPoolMetrics() external view returns (uint256 totalUsers_, uint256 averageDeposit, uint256 stakingRatio, uint256 poolTVL);
function getPoolConfiguration() external view returns (uint256 stakingAPY_, uint256 depositAPY_, uint256 minStakeAmount_, uint256 unstakingCooldown_, uint256 performanceFee_);
function getTotalDeposits() external view returns (uint256);
function getTotalStakes() external view returns (uint256);
function isPoolActive() external view returns (bool);
function getUserDepositHistory(address user) external view returns (UserDepositInfo[] memory);
function getUserWithdrawals(address user) external view returns (UserWithdrawalInfo[] memory);

Public state getters: stakingAPY(), depositAPY(), minStakeAmount(), unstakingCooldown(), performanceFee(), totalStakes(), totalUsers(), totalUserDeposits(), totalUserWithdrawals(), pendingUsdcWithdrawals(address), hasDeposited(address), userInfo(address).

Governance / emergency

  • updateStakingParameters(uint256 newStakingAPY, uint256 newMinStakeAmount, uint256 newUnstakingCooldown) — GOVERNANCE_ROLE; APY capped at 5000 bps. Emits PoolParameterUpdated(string indexed parameter, uint256 oldValue, uint256 newValue) for each field.
  • setPerformanceFee(uint256 _performanceFee) — GOVERNANCE_ROLE; max 2000 bps. Mint / redemption fees live in QuantillonVault, not here.
  • emergencyUnstake(address user, address recipient) — EMERGENCY_ROLE; force-unstakes a user's full staked balance to recipient (defaults to user).

Events

event UserDeposit(address indexed user, uint256 usdcAmount, uint256 qeuroMinted, uint256 timestamp);
event UserWithdrawal(address indexed user, uint256 qeuroBurned, uint256 usdcReceived, uint256 timestamp);
event UserDepositTracked(address indexed user, uint256 usdcAmount, uint256 qeuroReceived, uint256 oracleRatio, uint256 timestamp, uint256 blockNumber);
event UserWithdrawalTracked(address indexed user, uint256 qeuroAmount, uint256 usdcReceived, uint256 oracleRatio, uint256 timestamp, uint256 blockNumber);
event WithdrawalPending(address indexed user, uint256 amount);
event PendingWithdrawalClaimed(address indexed user, uint256 amount);
event QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 timestamp);
event QEUROUnstaked(address indexed user, uint256 qeuroAmount, uint256 timestamp);
event PoolParameterUpdated(string indexed parameter, uint256 oldValue, uint256 newValue);

HedgerPool

Contract: HedgerPool.sol
Interface: IHedgerPool.sol
Inherits: SecureUpgradeable, PausableUpgradeable

Function Signatures

enterHedgePosition(uint256 usdcAmount, uint256 leverage) → (uint256)

function enterHedgePosition(
    uint256 usdcAmount,
    uint256 leverage
) external returns (uint256 positionId)

Modifiers: whenNotPaused, nonReentrant
Events: HedgePositionOpened(address indexed hedger, uint256 indexed positionId, bytes32 packedData)
Requirements:

  • usdcAmount > 0
  • leverage >= 1 && leverage <= maxLeverage
  • Caller must be configured singleHedger
  • Fresh oracle price
  • Sufficient USDC balance and allowance

exitHedgePosition(uint256 positionId) → (int256)

function exitHedgePosition(uint256 positionId) external returns (int256 pnl)

Modifiers: whenNotPaused, nonReentrant
Events: HedgePositionClosed(address indexed hedger, uint256 indexed positionId, bytes32 packedData)
Requirements:

  • Position exists and is active
  • Caller owns the position

addMargin(uint256 positionId, uint256 usdcAmount)

function addMargin(uint256 positionId, uint256 usdcAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData)
Requirements:

  • Position exists and is active
  • Caller owns the position
  • usdcAmount > 0
  • Margin fee is split between local reward reserve and FeeCollector

removeMargin(uint256 positionId, uint256 usdcAmount)

function removeMargin(uint256 positionId, uint256 usdcAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData)
Requirements:

  • Position exists and is active
  • Caller owns the position
  • Maintains minimum margin ratio

claimHedgingRewards() → (uint256, uint256, uint256)

function claimHedgingRewards() external returns (uint256 interestDifferential, uint256 yieldShiftRewards, uint256 totalRewards)

Modifiers: nonReentrant Events: none (the former HedgingRewardsClaimed event was removed in v1.0.1; watch RewardReserveFunded and USDC transfers instead) Requirements:

  • Caller must be configured singleHedger
  • YieldShift reward component is settled once through YieldShift

withdrawPendingRewards(address recipient)

function withdrawPendingRewards(address recipient) external

Pull-based fallback for pending reward escrow after failed push-transfer.

hasActiveHedger() → (bool)

function hasActiveHedger() external view returns (bool)

Returns true when the configured single hedger has an active position.

getTotalEffectiveHedgerCollateral(uint256 currentPrice) → (uint256)

function getTotalEffectiveHedgerCollateral(uint256 currentPrice) external view returns (uint256 totalEffectiveCollateral)

Returns: Total effective hedger collateral in USDC (6 decimals)
Requirements:

  • currentPrice > 0

setSingleHedger(address hedger)

Governance entrypoint for bootstrap/reassignment. Assignment is synchronous: it succeeds only while the backing position (positionId 1) is inactive, and reverts otherwise. (The former delayed applySingleHedgerRotation path was removed as dead code — it could overwrite a live backing position.)

fundRewardReserve(uint256 amount)

Permissionless reserve top-up path for hedger rewards.

configureRiskAndFees(HedgerRiskConfig cfg)

Batch governance setter for risk + fee parameters:

  • minMarginRatio
  • maxLeverage
  • minPositionHoldBlocks
  • minMarginAmount
  • eurInterestRate
  • usdInterestRate
  • entryFee
  • exitFee
  • marginFee
  • rewardFeeSplit (1e18 = 100%)

configureDependencies(HedgerDependencyConfig cfg)

Batch governance setter for:

  • treasury
  • vault
  • oracle
  • yieldShift
  • feeCollector

Events

event HedgePositionOpened(address indexed hedger, uint256 indexed positionId, bytes32 packedData);
event HedgePositionClosed(address indexed hedger, uint256 indexed positionId, bytes32 packedData);
event MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData);
event RewardReserveFunded(address indexed funder, uint256 amount);
event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);
event EmergencyPositionClosed(address indexed hedger, uint256 indexed positionId, uint256 marginReturned, uint256 exposureRemoved);

stQEUROFactory

Contract: stQEUROFactory.sol
Interface: IStQEUROFactory.sol
Inherits: AccessControlUpgradeable, SecureUpgradeable

Function Signatures

registerVault(uint256 vaultId, string vaultName) -> (address stQEUROToken_)

function registerVault(uint256 vaultId, string calldata vaultName) external returns (address stQEUROToken_);

Modifiers: onlyRole(VAULT_FACTORY_ROLE)
Events: VaultRegistered(uint256 indexed vaultId, address indexed vault, address indexed stQEUROToken, string vaultName)
Requirements:

  • vaultId > 0
  • vaultName uppercase alphanumeric with length 1..12
  • unique vaultId, unique caller vault, unique vaultName
  • strict self-registration semantics: caller vault is inferred from msg.sender

getStQEUROByVaultId(uint256 vaultId) -> (address)

function getStQEUROByVaultId(uint256 vaultId) external view returns (address stQEUROToken_);

The address-keyed getStQEUROByVault helper was removed. Resolve each series by numeric vaultId.

getVaultById(uint256 vaultId) -> (address)

function getVaultById(uint256 vaultId) external view returns (address vault);

getVaultIdByStQEURO(address stQEUROToken_) -> (uint256)

function getVaultIdByStQEURO(address stQEUROToken_) external view returns (uint256 vaultId);

getVaultName(uint256 vaultId) -> (string)

function getVaultName(uint256 vaultId) external view returns (string memory vaultName);

updateYieldShift(address) / updateTokenImplementation(address) / updateOracle(address) / updateTreasury(address) / updateTokenAdmin(address)

Governance configuration setters affecting future vault token deployments and defaults.

Events

event VaultRegistered(uint256 indexed vaultId, address indexed vault, address indexed stQEUROToken, string vaultName);
event FactoryConfigUpdated(string indexed key, address oldValue, address newValue);

stQEUROToken

Contract: stQEUROToken.sol Interface: IstQEURO.sol Inherits: ERC4626Upgradeable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, SecureUpgradeable

Per-vault, yield-bearing ERC-4626 vault whose underlying asset() is QEURO. One proxy is deployed per staking vault by stQEUROFactory (live: stQEUROMORPHO1, vaultId = 2). There is no rebasing and no claim call: the share price totalAssets() / totalSupply() rises as credited QEURO yield vests (see the Staking Yield Distribution guide). Roles are GOVERNANCE_ROLE and EMERGENCY_ROLE (plus DEFAULT_ADMIN_ROLE and the SecureUpgradeable upgrade gate); there is no yield-manager role on this contract.

Function Signatures

Standard OpenZeppelin ERC-4626 surface; the four mutators are nonReentrant and whenNotPaused:

function deposit(uint256 assets, address receiver) external returns (uint256 shares);            // stake QEURO
function mint(uint256 shares, address receiver) external returns (uint256 assets);
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); // unstake
function totalAssets() external view returns (uint256);                                             // principal + vested QEURO
function convertToAssets(uint256 shares) external view returns (uint256);
function convertToShares(uint256 assets) external view returns (uint256);
function previewDeposit(uint256 assets) / previewMint(uint256 shares) / previewWithdraw(uint256 assets) / previewRedeem(uint256 shares)
function maxDeposit(address) / maxMint(address) / maxWithdraw(address owner) / maxRedeem(address owner)
function asset() external view returns (address);                                                   // QEURO
function syncVesting() external;                                                                      // advance lazy yield vesting

Notes:

  • deposit needs a prior QEURO approval to the stQEURO proxy; withdraw / redeem by a third party need share allowance from owner.
  • Redeeming the last outstanding shares also sweeps the rounding residual left by ERC-4626 round-down to that final exiter (ResidualSwept).
  • totalAssets() excludes unvested QEURO yield and includes principal plus the linearly vested portion. syncVesting() advances the schedule; it is permissionless while unpaused and may be called by governance while the token is paused for a post-upgrade initialization snapshot.
  • Current share price: convertToAssets(1e18). A holder's redeemable QEURO: previewRedeem(balanceOf(holder)).

yieldFee() / updateYieldParameters(uint256 _yieldFee)

The legacy yieldFee setting remains on the staking token for compatibility, but vault 1.5.0 ignores it for harvested and directly credited yield. The dapp retires this control for 1.5.0. Existing conversion execution costs still apply. The token setter remains GOVERNANCE_ROLE and emits YieldParametersUpdated(uint256 yieldFee).

updateTreasury(address _treasury)

GOVERNANCE_ROLE; emits TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury, address indexed caller).

emergencyWithdraw(address user)

EMERGENCY_ROLE, nonReentrant: burns all of user's shares and transfers the redeemable QEURO to that user.

Metadata / wiring views

vaultName() (e.g. "MORPHO1"), qeuro(), treasury(), TIME_PROVIDER(), version().

initialize(...)

Two initializers exist:

  • initialize(address admin, address _qeuro, address _treasury, address _timelock, string _vaultName) — used by stQEUROFactory; name / symbol become Staked Quantillon Euro {vaultName} / stQEURO{vaultName}.
  • initialize(address admin, address _qeuro, address, address, address _treasury, address _timelock) — legacy default-metadata initializer ("Staked Quantillon Euro" / "stQEURO").

Events

event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);                              // ERC-4626
event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares);  // ERC-4626
event YieldParametersUpdated(uint256 yieldFee);
event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury, address indexed caller);
event ResidualSwept(address indexed receiver, uint256 amount);

External Vault Adapters

The monolithic AaveVault contract was retired in the multi-vault refactor. External yield is provided by lightweight, non-upgradeable adapters that all implement the same IExternalStakingVault interface and are onboarded per vaultId via setup-external-vaults.sh. Adapters in src/core/vaults/: MetaMorphoStakingVaultAdapter (the live mainnet adapter, vaultId 2 — see Contract Addresses); AaveStakingVaultAdapter and MorphoStakingVaultAdapter wrap the MockAaveVault / MockMorphoVault mocks and exist for localhost / testnet only.

Interface: IExternalStakingVault.sol

Function Signatures

depositUnderlying(uint256 usdcAmount) → (uint256)

function depositUnderlying(uint256 usdcAmount) external returns (uint256 sharesReceived)

Deposits USDC into the wrapped third-party vault. Called by QuantillonVault.deployUsdcToVault(vaultId, usdcAmount).

withdrawUnderlying(uint256 usdcAmount) → (uint256)

function withdrawUnderlying(uint256 usdcAmount) external returns (uint256 usdcWithdrawn)

Withdraws USDC from the wrapped vault back to the protocol.

harvestYieldToVault() → (uint256)

function harvestYieldToVault() external returns (uint256 realizedYield)

Realizes accrued yield and transfers it to the calling vault (VAULT_MANAGER_ROLE). Invoked by QuantillonVault.harvestAndDistributeVaultYield(vaultId), which then splits the realized USDC by the staking ratio between stakers and treasury, paying the hedger only the configured haircut from gross staker yield.

totalUnderlying() → (uint256)

function totalUnderlying() external view returns (uint256 underlyingBalance)

Returns the adapter's current USDC-equivalent balance held in the wrapped vault.


YieldShift

Contract: YieldShift.sol
Interface: IYieldShift.sol
Inherits: SecureUpgradeable, PausableUpgradeable

Function Signatures

addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source)

function addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source) external

Modifiers: nonReentrant; the caller must be authorized for source via setYieldSourceAuthorization (otherwise NotAuthorized), and with strict binding enabled sourceToVaultId(msg.sender) must equal vaultId
Events: YieldAdded(uint256 yieldAmount, string indexed source, uint256 indexed timestamp)
Requirements:

  • vaultId > 0 and vault must be registered in stQEUROFactory
  • yieldAmount > 0
  • Sufficient USDC balance and allowance

updateYieldDistribution()

function updateYieldDistribution() external

Modifiers: whenNotPaused, nonReentrant
Events: YieldDistributionUpdated(uint256 newYieldShift, uint256 userYieldAllocation, uint256 hedgerYieldAllocation, uint256 indexed timestamp)

claimUserYield(address user) — ⚠️ REMOVED

This function has been removed. User yield accrues automatically through the stQEURO wrapper (the user share routes via creditVaultYield → stQEURO). (Hedger yield via claimHedgerYield is unaffected.)

claimHedgerYield(address hedger) → (uint256)

function claimHedgerYield(address hedger) external returns (uint256 yieldAmount)

Modifiers: whenNotPaused, nonReentrant
Events: HedgerYieldClaimed(address indexed hedger, uint256 yieldAmount, uint256 timestamp)

getPoolMetrics() → (uint256, uint256, uint256, uint256)

function getPoolMetrics() external view returns (
    uint256 userPoolSize,
    uint256 hedgerPoolSize,
    uint256 poolRatio,
    uint256 targetRatio
)

calculateOptimalYieldShift() → (uint256, uint256)

function calculateOptimalYieldShift() external view returns (
    uint256 optimalShift,
    uint256 currentDeviation
)

configureYieldModel(YieldModelConfig cfg)

Batch governance setter for:

  • baseYieldShift
  • maxYieldShift
  • adjustmentSpeed
  • targetPoolRatio

configureDependencies(YieldDependencyConfig cfg)

Batch governance setter for:

  • userPool
  • hedgerPool
  • mockAaveVault (vestigial: never read by YieldShift; pass address(0))
  • stQEUROFactory
  • treasury

setYieldSourceAuthorization(address source, bytes32 yieldType, bool authorized)

Governance setter to authorize/revoke a yield source and bind source type.

currentYieldShift(), userPendingYield(address), hedgerPendingYield(address), paused()

Direct state getters used by integrations and indexers.

Events

event YieldDistributionUpdated(uint256 newYieldShift, uint256 userYieldAllocation, uint256 hedgerYieldAllocation, uint256 indexed timestamp);
event YieldAdded(uint256 yieldAmount, string indexed source, uint256 indexed timestamp);
event HedgerYieldClaimed(address indexed hedger, uint256 yieldAmount, uint256 timestamp);
event SourceVaultBindingUpdated(address indexed source, uint256 indexed vaultId);
event SourceVaultBindingModeUpdated(bool enabled);

OracleRouter

Contract: OracleRouter.sol Interface: IOracle.sol Inherits: UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable — plain UUPS proxy (not SecureUpgradeable): _authorizeUpgrade is gated by UPGRADER_ROLE, held by the governance Safe, so upgrades execute in one Safe transaction with no timelock

Single oracle entry point for the protocol. All protocol contracts read prices only through OracleRouter; the underlying source can be switched by governance without touching consumers.

Routing slots (enum OracleType { CHAINLINK, MARKET }; live router version 1.1.2):

  • Slot 0 (CHAINLINK) — ChainlinkOracle, the fallback.
  • Slot 1 (MARKET) — the swappable market-price oracle: StorkOracle historically, currently HyperliquidEurUsdOracle, the active production oracle (activeOracle = 1). Named STORK before v1.1.0; the old storkOracle() getter is a deprecated alias of marketOracle().

Function Signatures

getEurUsdPrice() → (uint256, bool)

function getEurUsdPrice() external returns (uint256 price, bool isValid)

Proxies to the active oracle. Non-view by design — a fresh valid read commits the price into the deviation-baseline cache and emits PriceUpdated; integrators that only need a cheap read should use the cached getters.

Returns:

  • price: EUR/USD price (18 decimals)
  • isValid: Whether price is fresh and valid

getUsdcUsdPrice() → (uint256, bool)

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid)

getActiveOracle() → (OracleType)

Returns the currently active slot (1 on Base mainnet).

getOracleAddresses() → (address chainlinkAddress, address marketAddress)

Returns both slot addresses (the market slot currently returns the HyperliquidEurUsdOracle address).

marketOracle() → (IOracle) / storkOracle() → (IStorkOracle)

marketOracle() is the slot-1 getter (v1.1.0+). storkOracle() is the pre-1.1.0 name, kept as a deprecated ABI-compatible alias returning the same address.

switchOracle(OracleType newOracle)

function switchOracle(OracleType newOracle) external

Modifiers: onlyRole(ORACLE_MANAGER_ROLE) Events: OracleSwitched(uint8 oldOracle, uint8 newOracle, address caller)

One-transaction failover between slot 0 and slot 1 (e.g. switchOracle(0) falls back to Chainlink).

updateOracleAddresses(address _chainlinkOracle, address _marketOracle)

Modifiers: onlyRole(ORACLE_MANAGER_ROLE) Events: OracleAddressesUpdated

Points a slot at a new oracle contract — this is how HyperliquidEurUsdOracle was installed into slot 1.

Health and config views (getOracleHealth, getEurUsdDetails, getOracleConfig, getPriceFeedAddresses, checkPriceFeedConnectivity) and manager passthroughs (updatePriceBounds, updateUsdcTolerance, updatePriceFeeds, triggerCircuitBreaker, resetCircuitBreaker) forward to the active oracle.


ChainlinkOracle

Contract: ChainlinkOracle.sol Interface: IChainlinkOracle.sol Inherits: UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable — plain UUPS proxy (not SecureUpgradeable): _authorizeUpgrade is gated by UPGRADER_ROLE, held by the governance Safe, so upgrades execute in one Safe transaction with no timelock

Fallback EUR/USD oracle (router slot 0) and the protocol's USDC/USD source, reading Chainlink AggregatorV3 feeds.

Validation rules:

  • MAX_PRICE_STALENESS (EUR/USD): 2 hours
  • MAX_USDC_PRICE_STALENESS: 25 hours
  • MAX_PRICE_DEVIATION: 500 basis points (5%) circuit breaker
  • MAX_TIMESTAMP_DRIFT: 900 seconds (15 minutes)
  • EUR/USD price bounds: 0.80 – 1.40 (18 decimals)
  • USDC tolerance: 200 bps (2%), falls back to $1.00 outside tolerance

Function Signatures

getEurUsdPrice() → (uint256, bool)

function getEurUsdPrice() external view returns (uint256 price, bool isValid)

Returns:

  • price: EUR/USD price (18 decimals, normalized from the 8-decimal feed)
  • isValid: Whether price is fresh and valid

getUsdcUsdPrice() → (uint256, bool)

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid)

Returns:

  • price: USDC/USD price (18 decimals, normalized from the 8-decimal feed)
  • isValid: Whether price is fresh and valid

updatePriceFeeds(address eurUsdFeed, address usdcUsdFeed)

function updatePriceFeeds(address eurUsdFeed, address usdcUsdFeed) external

Modifiers: onlyRole(ORACLE_MANAGER_ROLE)
Events: PriceFeedsUpdated(address eurUsdFeed, address usdcUsdFeed)
Requirements:

  • eurUsdFeed != address(0)
  • usdcUsdFeed != address(0)

updatePriceBounds(uint256 minPrice, uint256 maxPrice)

function updatePriceBounds(uint256 minPrice, uint256 maxPrice) external

Modifiers: onlyRole(ORACLE_MANAGER_ROLE)
Events: PriceBoundsUpdated(uint256 minPrice, uint256 maxPrice)
Requirements:

  • minPrice < maxPrice

triggerCircuitBreaker()

function triggerCircuitBreaker() external

Modifiers: onlyRole(EMERGENCY_ROLE)
Events: CircuitBreakerTriggered(uint256 timestamp)

resetCircuitBreaker()

function resetCircuitBreaker() external

Modifiers: onlyRole(EMERGENCY_ROLE)
Events: CircuitBreakerReset(uint256 timestamp)


HyperliquidEurUsdOracle

Contract: HyperliquidEurUsdOracle.sol Interface: IHyperliquidOracle.sol (IOracle-compatible) Inherits: UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable — plain UUPS proxy (not SecureUpgradeable): _authorizeUpgrade is gated by UPGRADER_ROLE, held by the governance Safe, so upgrades execute in one Safe transaction with no timelock

The ACTIVE production EUR/USD oracle (router slot 1, live since 2026-06-25). EUR/USD is the Hyperliquid EUR perpetual mid-price, published on-chain into SlippageStorage by the off-chain publisher and read via getSlippageBySource(sourceId).midPrice (18 decimals). USDC/USD is delegated to ChainlinkOracle.

Validation rules:

  • maxPriceStaleness: 900 seconds default (15 min), hard-capped by HARD_MAX_STALENESS = 3600 seconds
  • EUR/USD price bounds: 0.80 – 1.40 (18 decimals)
  • MAX_PRICE_DEVIATION: 500 basis points (5%) circuit breaker vs last valid price
  • USDC tolerance: 200 bps (2%), falls back to $1.00
  • Stale or out-of-bounds price → isValid = false → dependent mint/redeem revert

Function Signatures

getEurUsdPrice() → (uint256, bool)

function getEurUsdPrice() external returns (uint256 price, bool isValid)

Non-view: a fresh valid read updates the deviation-baseline cache and emits PriceUpdated.

getUsdcUsdPrice() → (uint256, bool)

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid)

Delegated to the configured USDC source (ChainlinkOracle).

setMaxPriceStaleness(uint256 newMaxStaleness)

Modifiers: onlyRole(ORACLE_MANAGER_ROLE) — must be ≤ 3600 seconds. Events: MaxStalenessUpdated(uint256 oldStaleness, uint256 newStaleness)

updateSlippageSource(address _slippageStorage, uint8 _sourceId) / updateUsdcSource(address _usdcSource)

Modifiers: onlyRole(ORACLE_MANAGER_ROLE)

updatePriceBounds(uint256 minPrice, uint256 maxPrice) / updateUsdcTolerance(uint256 newToleranceBps)

Modifiers: onlyRole(ORACLE_MANAGER_ROLE)

triggerCircuitBreaker() / resetCircuitBreaker()

Modifiers: onlyRole(EMERGENCY_ROLE)

Health and config views: getOracleHealth, getEurUsdDetails, getOracleConfig, getPriceFeedAddresses, checkPriceFeedConnectivity.

Events

event PriceUpdated(uint256 eurUsdPrice, uint256 usdcUsdPrice, uint256 indexed timestamp);
event CircuitBreakerTriggered(uint256 attemptedPrice, uint256 lastValidPrice, string indexed reason);
event CircuitBreakerReset(address indexed admin);
event PriceBoundsUpdated(string indexed boundType, uint256 newMinPrice, uint256 newMaxPrice);
event SlippageSourceUpdated(address indexed newSlippageStorage, uint8 newSourceId);
event UsdcSourceUpdated(address indexed newUsdcSource);
event MaxStalenessUpdated(uint256 oldStaleness, uint256 newStaleness);

StorkOracle

Contract: StorkOracle.sol Inherits: UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable — plain UUPS proxy (not SecureUpgradeable): _authorizeUpgrade is gated by UPGRADER_ROLE, held by the governance Safe, so upgrades execute in one Safe transaction with no timelock

EUR/USD and USDC/USD feeds via the Stork Network, exposing the same IOracle surface as ChainlinkOracle. Parked: it previously occupied router slot 1 and was replaced there by HyperliquidEurUsdOracle on 2026-06-25. The contract remains deployed and can be re-installed via OracleRouter.updateOracleAddresses if needed.


FeeCollector

Contract: FeeCollector.sol Inherits: UUPSUpgradeable, AccessControlUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable — plain UUPS proxy (not SecureUpgradeable): _authorizeUpgrade is gated by GOVERNANCE_ROLE, held by the governance Safe, so upgrades execute in one Safe transaction with no timelock

Centralized protocol fee collection and distribution. Distribution ratios (initializer defaults, governance-adjustable, must sum to 10000 bps): treasury 60% / dev fund 25% / community 15%.

Function Signatures

collectFees(address token, uint256 amount, string sourceType)

Records fees pulled from an authorized protocol contract.

Modifiers: onlyFeeSource, whenNotPaused, nonReentrant

collectETHFees(string sourceType)

Payable ETH-fee variant.

Modifiers: onlyFeeSource, whenNotPaused, nonReentrant

distributeFees(address token)

Distributes collected fees to treasury, dev fund, and community fund according to configured ratios.

Modifiers: onlyRole(TREASURY_ROLE), whenNotPaused, nonReentrant

updateFeeRatios(uint256 _treasuryRatio, uint256 _devFundRatio, uint256 _communityRatio)

Modifiers: onlyRole(GOVERNANCE_ROLE) Requirements: _treasuryRatio + _devFundRatio + _communityRatio == 10000

updateFundAddresses(...)

Updates treasury / dev fund / community fund destinations.

Modifiers: onlyRole(GOVERNANCE_ROLE)

authorizeFeeSource(address feeSource) / revokeFeeSource(address feeSource)

Modifiers: onlyRole(GOVERNANCE_ROLE)

Events

event FeesCollected(address indexed token, uint256 amount, address indexed source, string indexed sourceType);
event FeesDistributed(address indexed token, uint256 totalAmount, uint256 treasuryAmount, uint256 devFundAmount, uint256 communityAmount);
event FeeRatiosUpdated(uint256 treasuryRatio, uint256 devFundRatio, uint256 communityRatio);
event FundAddressesUpdated(address treasury, address devFund, address communityFund);

TimeProvider

Contract: TimeProvider (in src/libraries/TimeProviderLibrary.sol) — deployed directly, not behind a proxy

Centralized block.timestamp wrapper used across core contracts, with governance-controlled offset support for test environments.

Function Signatures

currentTime() → (uint256) / rawTimestamp() → (uint256)

Public views: offset-adjusted time and raw block timestamp.

setTimeOffset(int256 newOffset, string reason)

Modifiers: onlyRole(GOVERNANCE_ROLE) — offset bounded (max 7 days) to prevent abuse.

advanceTime(uint256 amount) / resetTime()

Modifiers: onlyRole(GOVERNANCE_ROLE)

setEmergencyMode(bool enabled) / emergencyResetTime()

Modifiers: onlyRole(EMERGENCY_ROLE)

getTimeInfo() / timeDiff(uint256 t1, uint256 t2)

Public views.

Events

event TimeOffsetChanged(address indexed changer, int256 oldOffset, int256 newOffset, string reason, uint256 timestamp);
event EmergencyModeChanged(bool enabled, address indexed changer, uint256 timestamp);
event TimeReset(address indexed resetter, uint256 timestamp);

Access Control Roles

RoleWhereDescription / key functions
DEFAULT_ADMIN_ROLEall contractsRole administration; QEURO supply cap and rate limits (updateMaxSupply, updateRateLimits); treasury / fee-collector wiring; token/ETH recovery; controller bootstrap only (setTimelock requires the current controller after bootstrap)
GOVERNANCE_ROLEQuantillonVault, QEUROToken-adjacent core (QTIToken, UserPool, HedgerPool, YieldShift, stQEUROFactory, stQEUROToken), FeeCollector, TimeProviderParameter updates, dependency wiring, fee ratios, time offsets; on FeeCollector it also gates _authorizeUpgrade
EMERGENCY_ROLEcore contracts, FeeCollector, oracles, SlippageStorage, TimeProviderPause/unpause, emergency position close / unstake / withdraw, circuit breakers
UPGRADER_ROLEOracleRouter, ChainlinkOracle, HyperliquidEurUsdOracle, LighterEurUsdOracle (inert), StorkOracle, SlippageStorage, TimeProvider_authorizeUpgrade on the plain-UUPS proxies — held by the Safe and effective immediately (no timelock). The eight SecureUpgradeable proxies (QuantillonVault, QEUROToken, QTIToken, UserPool, HedgerPool, YieldShift, stQEUROFactory, stQEUROToken) are instead gated by their timelock pointer, the 12 h OpenZeppelin TimelockController
MINTER_ROLE / BURNER_ROLEQEUROTokenMint / burn QEURO (held by QuantillonVault)
PAUSER_ROLEQEUROTokenpause / unpause, setMintingKillswitch
COMPLIANCE_ROLEQEUROTokenWhitelist / blacklist management, whitelist mode
VAULT_OPERATOR_ROLEQuantillonVaultdeployUsdcToVault (move idle USDC into an external vault adapter)
YIELD_DISTRIBUTOR_ROLEQuantillonVaultharvestAndDistributeVaultYield, creditVaultYield
VAULT_FACTORY_ROLEstQEUROFactoryregisterVault (granted to QuantillonVault for self-registration)
VAULT_MANAGER_ROLEexternal vault adaptersdepositUnderlying / withdrawUnderlying / harvestYieldToVault (held by QuantillonVault)
ORACLE_MANAGER_ROLEOracleRouter, ChainlinkOracle, HyperliquidEurUsdOracle, LighterEurUsdOracle (inert), StorkOracleswitchOracle, updateOracleAddresses, feed / bounds / staleness / source configuration
MANAGER_ROLE / WRITER_ROLESlippageStorageStore configuration (MANAGER_ROLE) / publishing the venue mid on-chain (WRITER_ROLE)
TREASURY_ROLE / FEE_SOURCE_ROLEFeeCollectordistributeFees / contracts allowed to push fees (QuantillonVault, HedgerPool)
YIELD_MANAGER_ROLEYieldShiftInitializer-granted legacy role; the public update interval applies normally, and forceUpdateYieldDistribution requires GOVERNANCE_ROLE

On Base mainnet the governance Safe holds operational governance, upgrade, emergency and oracle-manager roles as configured per contract. The 23 September 2026 activation transferred core default-admin roles to the controller while retaining Safe operational roles; direct-Safe oracle/fee administration is unchanged. Read live hasRole values to verify current authority. Operational roles are delegated to dedicated service wallets: VAULT_OPERATOR_ROLE and YIELD_DISTRIBUTOR_ROLE to keeper wallets, an additional EMERGENCY_ROLE grant on the vault to the hedging watchdog, and SlippageStorage WRITER_ROLE to the off-chain price publisher (currently also held by the deployer EOA). OracleRouter itself holds ORACLE_MANAGER_ROLE and EMERGENCY_ROLE on the market oracle so that its admin passthroughs work. There is no liquidator role — liquidation mode is a protocol-level state (0 < vault CR <= critical ratio (currently 101%)), not a per-position keeper action.


Constants and Limits

Configuration checked against finalized Base block 51,985,907 on 30 September 2026; see Production Protocol Reference. Values marked settable are current live values that governance can change, not immutable constants.

QuantillonVault

  • mintFee: 0 (settable, max 5% = 5e16)
  • redemptionFee: 0 (settable, max 5%; also applied to liquidation-mode redemptions)
  • minCollateralizationRatioForMinting: 102.5% live (1.025e20, since 2026-09-02) — governance-settable (initializer default 105% = 105e18; hard floor 101%)
  • criticalCollateralizationRatio: 101% (101e18) — liquidation mode at or below this protocol CR
  • MAX_PRICE_DEVIATION: 200 bps (2%) between cached and live oracle price
  • hedgerStakingYieldHaircutBps: 0 live on 30 September 2026; governance-settable from 0 to 10,000 bps of gross staker yield. The annual-funding model is retired.

QEUROToken

  • Supply model: no fixed tokenomic supply cap — supply is economically bounded by hedging capacity (minting requires the protocol CR to stay above the governance-set minting floor)
  • maxSupply: administrative safety ceiling, currently 100,000,000 QEURO (DEFAULT_MAX_SUPPLY; governance-raisable at any time via updateMaxSupply, only constrained to ≥ current supply)
  • Decimals: 18
  • Mint and burn rate limiting (supply-abuse guardrail, global): each capped at 10,000,000 QEURO per 300-block window (~10 min on Base) — rateLimitCaps() returns (mint, burn), both initialised to MAX_RATE_LIMIT and live at 10M / 10M; adjustable downward by updateRateLimits (DEFAULT_ADMIN_ROLE). RATE_LIMIT_RESET_PERIOD = 300 blocks.

QTIToken

  • TOTAL_SUPPLY_CAP: 100,000,000 QTI — current supply is 0 (dormant: no mint path is wired)
  • MIN_LOCK_TIME: 7 days · MAX_LOCK_TIME: 365 days
  • MAX_VE_QTI_MULTIPLIER: 4× voting power
  • proposalThreshold: 100,000 QTI · quorumVotes: 1,000,000 QTI (settable)
  • Voting period: 3 days minimum, 14 days maximum · PROPOSAL_EXECUTION_DELAY: 2 days

UserPool

  • stakingAPY: 800 bps (8%) · depositAPY: 400 bps (4%) (settable)
  • minStakeAmount: 100 QEURO (settable)
  • unstakingCooldown: 7 days (settable)
  • performanceFee: 0 (settable)

HedgerPool

  • coreParams().maxLeverage: 40× (settable via configureRiskAndFees; the MAX_LEVERAGE constant = 65535 is a storage bound; MAX_CONFIGURABLE_LEVERAGE caps configuration at 40) · coreParams().minMarginRatio: 250 bps (2.5%) live since 2026-09-02 — governance-set via configureRiskAndFees: 500 bps at launch, hard floor DEFAULT_MIN_MARGIN_RATIO_BPS = 250 bps since v1.0.8
  • MAX_MARGIN_RATIO: 5000 bps (50%, i.e. 2× minimum leverage)
  • minMarginAmount: 0 live (settable; initializer default 100 USDC) · minPositionHoldBlocks: 0 live (settable; initializer default 5 blocks)
  • entryFee / exitFee / marginFee: 0 (settable)
  • eurInterestRate / usdInterestRate: 350 / 450 bps (settable)
  • HedgerPool rewardFeeSplit: 0 of its operation fees routed to the reserve (settable). The separate vault hedgerRewardFeeSplit is 20% of collected vault fees; neither is a reward-claim tax.
  • Single-hedger model (setSingleHedger; the delayed rotation path was removed, see setSingleHedger above); liquidation is driven by the vault-level critical CR (<= 101%), not a per-position threshold constant

stQEURO

  • yieldFee: legacy token setting, ignored by QuantillonVault 1.5.0.

YieldShift

  • baseYieldShift: 50% · maxYieldShift: 90% (settable)
  • MIN_HOLDING_PERIOD: 7 days · TWAP_PERIOD: 24 hours · MAX_HISTORY_LENGTH: 1000

Oracles

  • ChainlinkOracle: EUR/USD staleness 2 h · USDC/USD staleness 25 h · 5% deviation breaker · bounds 0.80–1.40 · USDC tolerance 2%
  • HyperliquidEurUsdOracle: staleness 900 s (hard cap 3600 s) · same bounds, breaker, and tolerance

External Vault Adapters

  • No fixed exposure/rebalance constants — adapters are thin pass-throughs to the wrapped vault.
  • USDC is deployed/withdrawn per vaultId under governance control via QuantillonVault.deployUsdcToVault / harvestAndDistributeVaultYield.

Error Handling

All functions revert with custom errors (no require strings). Errors are declared in the domain error libraries under src/libraries/ and are part of each contract's ABI, so they decode with the contract ABI or with the library ABI. OpenZeppelin errors (AccessControlUnauthorizedAccount, EnforcedPause, ReentrancyGuardReentrantCall, ERC20Insufficient*, ERC4626ExceededMax*, UUPSUnauthorizedCallContext, ...) surface unchanged.

// Revert with a library error
if (amount == 0) revert CommonErrorLibrary.InvalidAmount();

Error Catalogue (from src/libraries/*ErrorLibrary.sol)

CommonErrorLibrary (shared by all contracts)

GroupErrors
Input / validationInvalidAmount, ZeroAddress, InvalidAddress, InvalidParameter, InvalidCondition, InvalidRatio, InvalidTime, InvalidThreshold, InvalidShiftRange, ArrayLengthMismatch, BatchSizeTooLarge, EmptyArray, DivisionByZero, PercentageTooHigh, ConfigValueTooHigh, ConfigValueTooLow, RateLimitTooHigh
AccessNotAuthorized, NotAdmin, InvalidAdmin, NotGovernance, NotEmergencyRole, NotLiquidatorRole, NotVaultManager, NotYieldManager, NotWhitelisted
Wiring / stateInvalidTreasury, InvalidToken, InvalidOracle, InvalidVault, AlreadyInitialized, NotInitialized, NotActive, NoChangeDetected, EmergencyModeActive
Balances / limitsInsufficientBalance, AboveLimit, WouldExceedLimit, BelowThreshold, ExcessiveSlippage, InsufficientCollateralization, HoldingPeriodNotMet, TooManyPositions, PositionNotActive, LiquidationCooldown
OracleInvalidPrice, InvalidOraclePrice (an invalid / stale oracle read reverts mintQEURO / redeemQEURO with InvalidOraclePrice)
YieldInsufficientYield, YieldCalculationError, YieldClaimFailed
Governance (QTI)VotingPeriodTooShort, VotingPeriodTooLong, VotingNotStarted, VotingEnded, VotingNotEnded, AlreadyVoted, NoVotingPower, InsufficientVotingPower, ProposalAlreadyExecuted, ProposalCanceled, ProposalAlreadyCanceled, ProposalFailed, QuorumNotMet, ExecutionTimeNotReached, LockTimeTooShort, LockTimeTooLong
RecoveryETHTransferFailed, NoETHToRecover, CannotRecoverOwnToken

TokenErrorLibrary (QEUROToken / QTIToken): MintingDisabled, BlacklistedAddress, NewCapBelowCurrentSupply, LockNotExpired, NothingToUnlock, RateLimitExceeded, AlreadyBlacklisted, NotBlacklisted, AlreadyWhitelisted, PrecisionTooHigh, TooManyDecimals

HedgerPoolErrorLibrary (HedgerPool): FlashLoanAttackDetected, InvalidPosition, InvalidHedger, OnlyVault, RewardOverflow, InsufficientMargin, MarginExceedsMaximum, PositionSizeExceedsMaximum, EntryPriceExceedsMaximum, LeverageExceedsMaximum, TimestampOverflow, TotalMarginExceedsMaximum, TotalExposureExceedsMaximum, NewMarginExceedsMaximum, InvalidLeverage, LeverageTooHigh, MarginRatioTooLow, MarginRatioTooHigh, PositionOwnerMismatch, PositionClosureRestricted, InsufficientHedgerCapacity, NoActiveHedgerLiquidity, HedgerHasActivePosition, MinHoldPeriodNotElapsed

VaultErrorLibrary (QuantillonVault): FeeTooHigh

All of these are parameterless (error Name();), so matching on the 4-byte selector (keccak256("Name()")[:4]) is sufficient. Pausing surfaces as OpenZeppelin EnforcedPause().


Gas Optimization

Best Practices

  1. Use view functions for read-only operations
  2. Batch operations when possible
  3. Cache storage reads in loops
  4. Use events instead of storage for logging
  5. Implement proper access control to prevent unauthorized calls

Gas Figures

No static gas table is maintained here: figures drift with every implementation upgrade. Generate them from the current source with make gas-analysis (outputs under scripts/results/gas-analysis/) or forge test --gas-report.


Integration Patterns

Frontend Integration

// Web3.js example
const contract = new web3.eth.Contract(abi, address);

// Call view function
const result = await contract.methods.getProtocolCollateralizationRatio().call();

// Send transaction
const tx = await contract.methods.mintQEURO(usdcAmount, minQeuroOut)
    .send({ from: userAddress });

Backend Integration

# Web3.py example
from web3 import Web3

w3 = Web3(Web3.HTTPProvider(rpc_url))
contract = w3.eth.contract(address=contract_address, abi=abi)

# Call view function
result = contract.functions.getProtocolCollateralizationRatio().call()  # 1e20 == 100%

# Send transaction
tx_hash = contract.functions.mintQEURO(usdc_amount, min_qeuro_out).transact({
    'from': user_address
})

Solidity Integration Examples

Basic QEURO Minting

// 1. Approve USDC spending
usdc.approve(vaultAddress, usdcAmount);

// 2. Quote the mint (QEURO is 18 decimals, USDC is 6 — never derive the floor from usdcAmount)
ExecutionPricing.Quote memory quote = ExecutionPricing(vault.executionPricing()).previewMint(usdcAmount);
uint256 expectedQeuro = quote.amountOut;
uint256 minQeuroOut = (expectedQeuro * 95) / 100; // 5% slippage tolerance

// 3. Mint QEURO with slippage protection
vault.mintQEURO(usdcAmount, minQeuroOut);

Staking QEURO

// 1. Approve QEURO spending
qeuro.approve(userPoolAddress, qeuroAmount);

// 2. Stake QEURO — UserPool functions take arrays (one element for a single stake)
uint256[] memory amounts = new uint256[] (1);
amounts[0] = qeuroAmount; // must be >= userPool.minStakeAmount()
userPool.stake(amounts);

// There is no staking-reward claim. Protocol yield for users accrues automatically
// through the stQEURO ERC-4626 token (rising share price) — deposit QEURO into the
// per-vault stQEURO (stQEUROFactory.getStQEUROByVaultId(vaultId)) to earn it.

Opening a Hedge Position

// 1. Approve USDC spending (caller must be the configured single hedger)
usdc.approve(hedgerPoolAddress, marginAmount);

// 2. Open position with 5x leverage (max leverage: 40x)
uint256 positionId = hedgerPool.enterHedgePosition(marginAmount, 5);

// 3. Monitor hedger activity / claim rewards
bool hedgerActive = hedgerPool.hasActiveHedger();
(uint256 interestDiff, uint256 ysRewards, uint256 total) = hedgerPool.claimHedgingRewards();

Governance Participation

Note: QTI is currently dormant (supply 0, no mint path wired) — these calls become functional after the activation upgrade.

// 1. Lock QTI for voting power
qti.lock(lockAmount, lockDuration);

// 2. Create proposal
uint256 proposalId = qti.createProposal(
    "Update protocol parameters",
    block.timestamp + 1 days,
    block.timestamp + 7 days
);

// 3. Vote on proposal
qti.vote(proposalId, true); // Vote yes

Security Considerations

  1. Always validate return values from view functions
  2. Check contract state before making transactions
  3. Use slippage protection for all swaps
  4. Monitor oracle prices for freshness
  5. Implement proper error handling for all interactions
  6. Use events for transaction monitoring
  7. Follow access control patterns for role-based operations

Support

For technical support and questions:


This technical reference is maintained by Quantillon Labs and updated with each protocol version.

Yield and collateralization gates

The public mint floor remains the governance value read from minCollateralizationRatioForMinting; clients must read this value on-chain rather than use a frontend default. Yield crediting uses a separate gate: current collateralization must be strictly greater than max(101%, criticalCollateralizationRatio), projected collateralization must remain at least 100%, and the cached oracle, active hedger, execution book, QEURO token state, and hedger capacity must all pass. A failed harvest reverts the entire transaction so adapter yield remains available for a later retry.

Quantillon Protocol Quick Start

Signed quotes are active on Base since 17 October 2026. Normal mint and redemption must use executeWithQuote(bytes,bytes) on the authorized Vault or UserPool target. Bare conversion calls and the legacy pricing module's previews are not the current integration path.

This ethers v6 example uses the UserPool conversion route. It does not use UserPool's optional staking accounting. The later staking example deposits QEURO directly into the ERC-4626 series. Use the address inventory and production guide, and test with an isolated fork before integration.

Connect and pin the intended deployment

import { BrowserProvider, Contract, Interface, keccak256, parseUnits, ZeroAddress } from 'ethers';

const provider = new BrowserProvider(window.ethereum);
if ((await provider.getNetwork()).chainId !== 8453n) throw new Error('Select Base');
const signer = await provider.getSigner();
const owner = await signer.getAddress();
const vaultAddress = '0x833E5Ba510a241b21F1C60c987D1c49eB52E4a07';
const poolAddress = '0x712bCc77e7aa53C79870A40d044D440Ad2901bF2';
const moduleAddress = '0x076F86a591258957665b65c04F04B706D00EaEBa';
const qeuroAddress = '0x69aD4e6c49d6275D0e11b5515D98a89f029869AA';
const usdcAddress = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const factoryAddress = '0x0382B0b9FB6Ff737209C3B31D727BB9d2E2bcb53';
const tokenAbi = [
  'function approve(address spender,uint256 amount) returns (bool)',
  'function balanceOf(address owner) view returns (uint256)',
];
const usdc = new Contract(usdcAddress, tokenAbi, signer);
const qeuro = new Contract(qeuroAddress, tokenAbi, signer);
const vault = new Contract(vaultAddress, [
  'function executionPricing() view returns (address)',
  'function signedExecutionEnabled() view returns (bool)',
], provider);
const pool = new Contract(poolAddress, [
  'function executeWithQuote(bytes callData,bytes authorization) returns (bytes)',
], signer);
const route = new Interface([
  'function deposit(uint256[] amounts,uint256[] minimums)',
  'function withdraw(uint256[] amounts,uint256[] minimums)',
]);

Approval, quote and review

For a mint, approve USDC to the selected target before requesting an executable quote:

const inputUsdc = parseUnits('100', 6); // illustrative user-selected amount
await (await usdc.approve(poolAddress, inputUsdc)).wait();

The dapp's authenticated gateway accepts POST /api/quotes with a JSON body such as {"action":"MINT","amountIn":"100000000","chainId":8453,"route":"USER_POOL"} and the wallet identity associated with the authenticated session. The frontend supplies credentials: 'include' and x-wallet-address; a header alone does not establish a login session. Integrators must arrange access to the quote service. POST /api/quotes/preview returns a preview, not an executable authorization.

An executable envelope contains chainId, module, target, callData, authorization and a quote with wallet/caller, action, exact input/output, observation time, validity times, nonce, epoch and hashes. Display the output and deadline for user review. Use integer base units: USDC has 6 decimals and QEURO has 18.

Submit the reviewed UserPool quote

The function below accepts an envelope already obtained from the quote service, plus the exact action, input and output reviewed by the user. It checks the deployment and allowed inner call before sending anything. The contract validates the signatures and remaining protocol guards.

async function settleReviewedPoolQuote(envelope, reviewed) {
  const same = (a, b) => a.toLowerCase() === b.toLowerCase();
  if (!['MINT', 'REDEEM'].includes(reviewed.action)) throw new Error('Invalid action');
  if (reviewed.amountIn <= 0n || reviewed.amountOut <= 0n) throw new Error('Invalid amount');
  if ((await provider.getNetwork()).chainId !== 8453n ||
      !same(await signer.getAddress(), owner)) throw new Error('Wallet or chain changed');
  if (!await vault.signedExecutionEnabled() ||
      !same(await vault.executionPricing(), moduleAddress)) throw new Error('Deployment changed');
  const q = envelope.quote;
  const action = reviewed.action === 'MINT' ? 0 : 1;
  const functionName = action === 0 ? 'deposit' : 'withdraw';
  const expectedCall = route.encodeFunctionData(functionName, [
    [reviewed.amountIn], [reviewed.amountOut],
  ]);
  if (envelope.chainId !== 8453 || !same(envelope.target, poolAddress) ||
      !same(envelope.module, moduleAddress) || !same(q.user, owner) ||
      !same(q.caller, poolAddress) || q.action !== action ||
      BigInt(q.amountIn) !== reviewed.amountIn || BigInt(q.amountOut) !== reviewed.amountOut ||
      envelope.callData.toLowerCase() !== expectedCall.toLowerCase() ||
      q.callHash.toLowerCase() !== keccak256(envelope.callData).toLowerCase()) {
    throw new Error('Quote differs from the reviewed operation');
  }
  const checkTime = () => {
    const now = BigInt(Math.floor(Date.now() / 1000));
    if (BigInt(q.validAfter) > now || BigInt(q.observedAt) > now ||
        BigInt(q.validUntil) < now + 10n ||
        BigInt(q.validUntil) - BigInt(q.observedAt) > 45n) {
      throw new Error('Request and review a fresh quote');
    }
  };
  checkTime();
  await pool.executeWithQuote.staticCall(envelope.callData, envelope.authorization);
  checkTime();
  const tx = await pool.executeWithQuote(envelope.callData, envelope.authorization);
  // Persist tx.hash immediately; reconcile its receipt before any retry.
  return tx;
}

The 10-second remaining-time check is a client convenience, not an inclusion guarantee. The onchain maximum is 45 seconds from the market observation. Simulation does not reserve public liquidity, and state changes or wallet delays can still cause a revert. Never modify the signed calldata or silently refresh the user's accepted output.

Stake QEURO directly

const factory = new Contract(factoryAddress, [
  'function getStQEUROByVaultId(uint256 vaultId) view returns (address)',
], provider);
const seriesAddress = await factory.getStQEUROByVaultId(2n);
if (seriesAddress === ZeroAddress) throw new Error('No staking series');
const series = new Contract(seriesAddress, [
  'function asset() view returns (address)',
  'function previewDeposit(uint256 assets) view returns (uint256)',
  'function deposit(uint256 assets,address receiver) returns (uint256)',
  'function balanceOf(address owner) view returns (uint256)',
  'function convertToAssets(uint256 shares) view returns (uint256)',
  'function redeem(uint256 shares,address receiver,address owner) returns (uint256)',
], signer);
if ((await series.asset()).toLowerCase() !== qeuroAddress.toLowerCase()) {
  throw new Error('Unexpected staking asset');
}
const assets = parseUnits('10', 18); // user-selected amount, must be available
if (await qeuro.balanceOf(owner) < assets) throw new Error('Insufficient QEURO');
await (await qeuro.approve(seriesAddress, assets)).wait();
const expectedShares = await series.previewDeposit(assets);
if (expectedShares === 0n) throw new Error('Deposit would produce no shares');
await series.deposit.staticCall(assets, owner);
await (await series.deposit(assets, owner)).wait();
const shares = await series.balanceOf(owner);
const vestedAssets = await series.convertToAssets(shares);

Standard ERC-4626 deposit does not accept a minimum-share argument: a preview is informational, not slippage protection. The vault's signed mintAndStakeQEURO inner operation has an explicit minimum-share parameter for a combined mint/stake. Yield increases the assets represented by shares as it vests; no separate staking-reward claim is needed. See Yield Distribution 1.5.0.

Next steps

Integration Examples covers redemption, unstaking and transaction recovery. Dapp Compatibility lists release checks. Use the compiled ABI matching each active implementation, including library errors.

Integration Examples

Use the ethers v6 setup and contract objects from Quick Start. These examples illustrate client integration; simulate and test them on an isolated fork before use. They are not a guarantee of current liquidity or transaction success.

Normal redemption

Approve the input QEURO to the same UserPool target used in Quick Start:

const inputQeuro = parseUnits('10', 18);
await (await qeuro.approve(poolAddress, inputQeuro)).wait();

Then request an executable quote with action: 'REDEEM', amountIn: inputQeuro.toString(), chainId: 8453 and route: 'USER_POOL'. Display its exact USDC output and expiry. After review, pass the envelope and the reviewed values to settleReviewedPoolQuote from Quick Start, record the returned transaction hash and await its receipt. The function validates that the inner call is precisely withdraw([inputQeuro], [reviewedUsdcOutput]).

Normal signed redemption does not use the retired module's degraded-reference fallback. The current emergency-redemption budget is 0 QEURO, so missing quotes do not automatically open an alternative exit. Protocol liquidation mode uses a separate proportional-backing payout rule, still subject to signed settlement and current contract guards. Never set a zero minimum to bypass an unavailable quote.

Unstake shares into QEURO

const sharesToRedeem = parseUnits('1', 18); // share units, not QEURO assets
const receivedQeuro = await series.redeem.staticCall(sharesToRedeem, owner, owner);
if (receivedQeuro === 0n) throw new Error('Redemption produces no QEURO');
await (await series.redeem(sharesToRedeem, owner, owner)).wait();

This returns QEURO, not USDC. A later QEURO-to-USDC redemption is a separate operation with its own quote and approval. Standard ERC-4626 redemption has no minimum-assets argument; simulations do not protect against all intervening state changes. Direct stQEURO redemption is separate from UserPool's unstaking cooldown.

Portfolio reads

Use qeuro.balanceOf(owner) for unstaked QEURO, series.balanceOf(owner) for shares and series.convertToAssets(shares) for currently recognized assets. Raw assets used in the harvest allocation include unvested credit and can differ from vested ERC-4626 assets.

The provider's APY, UserPool's configured accounting APY, a realized share-price return and future yield are different metrics. Do not label one as a guarantee of another.

Optional and privileged interfaces

  • UserPool: deposit and withdrawal inner methods accept arrays and must use the signed wrapper for conversion; optional staking methods have their own accounting. Its bookkeeping and unstaking cooldown are not the direct stQEURO flow.
  • HedgerPool: reference-dependent position operations use executeWithReference or scoped removeMarginWithReference, retaining their existing ownership and role checks. Client-side visibility does not grant that authority. HedgerPool and Hyperliquid margin are separate balances.
  • Yield keeper: harvest conversion uses its bounded signed authorization as well as the configured distributor role and valid strategy/liquidity/collateral conditions. Daily scheduling is an operated service, not an autonomous Solidity timer.
  • QTI: supply is zero and governance is dormant. Examples of lock/propose/vote are API descriptions, not currently usable public governance.
  • Administration: core default-admin operations require the controller; retained Safe roles and peripheral administration have different paths. Resolve current roles before constructing calls.

Transaction recovery

Record a submitted transaction hash and check its receipt before retrying. A network timeout does not prove a transaction failed. Reconcile pending/confirmed state and the wallet nonce, then obtain a fresh quote and ask the user to review any changed output. Do not automatically resubmit a deposit or mint after an ambiguous response.

For revert decoding use the ABI matching the active implementation, including relevant library errors. Report stale/invalid pricing, insufficient capacity, pauses, allowances and minimum-output failures separately where the decoded error supports that distinction. Never silently widen a user's tolerance.

See Production Protocol Reference, API Reference and Security Guide.

Quantillon Protocol Architecture

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

Current production controls

See Production Protocol Reference for the dated configuration. The oracle supplies valuation; SignedExecutionPricing verifies exact transaction-bound quotes and signed hedge admission; SignedReferenceSource supplies independently checked valuation reports. Its spread reserve is excluded from backing. A valid oracle mid alone is not an executable mint/redeem quote. Core role administration belongs to the TimelockController; peripheral administration remains with the Safe.

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 applicable core admin controller to grant governance permissions through the timelock, along with a mint/distribution upgrade.
  • 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(); totalAssets() includes principal plus linearly vested QEURO yield, while newly credited yield remains excluded until syncVesting() advances the schedule
  • 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 ERC1967Proxy and shared stQEUROToken implementation
  • Deterministic registry and lookup mappings:
    • vaultId -> stQEURO token
    • vault -> stQEURO token
    • stQEURO token -> vaultId
  • Strict vault self-registration model (msg.sender is the registered vault)
  • Validation and uniqueness guarantees for vaultId and vaultName (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 IOracle reads 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
  • updateOracleAddresses repoints a slot; OracleSwitched event 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:EUR perpetual mid — the venue where the protocol's EUR/USD hedge executes — so QEURO mint/redeem aligns with the hedge. Reads signed valuation from SignedReferenceSource (reports delivered with transactions) and delegates USDC/USD to the ChainlinkOracle. 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 TemporalNumericValue feeds (legacy/parked; the slot-1 position is now occupied by HyperliquidEurUsdOracle).
  • Mock versions available (MockChainlinkOracle, MockStorkOracle) for local/testnet.
  • Full design: Oracle Architecture.

9b. Signed reference and execution modules

SignedReferenceSource 1.0.0 accepts authenticated reports with their original observation time and an independent-reference check. SignedExecutionPricing 1.1.0 validates exact execution authorizations and cumulative hedge-capacity reports. The production maximum quote lifetime is 45 seconds; the separate normal report-age limit is 60 seconds.

SlippageStorage and publication batchers remain historical deployments. The recurring publisher is retired. See Signed Quotes in Production for binding addresses and the zero emergency budget.

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 vaultId through stQEUROFactory to 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 vaultId via QuantillonVault.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 IExternalStakingVault adapters wrap each external vault
  • Factory Registry: stQEUROFactory maps vaultId to adapter + stQEURO series
  • Yield Optimization: Dynamic allocation strategies
  • Vault-Aware Routing: harvested external-vault yield is split by QuantillonVault.harvestAndDistributeVaultYield (staked allocation after haircut / unstaked allocation to treasury / haircut only to hedger); 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/burn
  • PAUSER_ROLE: QEUROToken emergency pause and minting killswitch
  • COMPLIANCE_ROLE: QEUROToken blacklist/whitelist management
  • GOVERNANCE_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 breakers
  • VAULT_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-registration
  • TREASURY_ROLE / FEE_SOURCE_ROLE: FeeCollector — fee distribution / authorized fee sources
  • ORACLE_MANAGER_ROLE: OracleRouter / ChainlinkOracle / HyperliquidEurUsdOracle / StorkOracle / LighterEurUsdOracle (inert) — feed updates, oracle switching
  • MANAGER_ROLE / WRITER_ROLE: SlippageStorage — store configuration / on-chain mid publishing
  • UPGRADER_ROLE: the plain-UUPS proxies (oracles, SlippageStorage) — direct Safe upgrades; the SecureUpgradeable core proxies are gated by the 12 h TimelockController instead

Security Patterns

Reentrancy Protection:

  • nonReentrant modifier 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

User approves USDC to the chosen Vault or UserPool target
  -> quote service returns exact execution + reference + capacity authorizations
  -> user reviews amount, output and expiry
  -> executeWithQuote(callData, authorization)
  -> signature, call binding, nonce, epoch and freshness checks
  -> reference delivery and current collateral/capacity checks
  -> USDC transfer, backing/spread accounting and QEURO mint
  -> receipt confirms Base settlement
  -> hedge engine reconciles and executes the separate venue hedge

All Base-side effects revert together if a settlement check fails. The later Hyperliquid operation is not atomic with Base. OracleRouter forwards valuation reads to HyperliquidEurUsdOracle and its signed reference source. A rejected price with isValid = false blocks the operation. The non-view oracle read can update its deviation baseline; simulations do not persist that update.

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) │
     │              │◀─────────────────┤            │              │
     │              │ grossStaker = floor(realizedYield × rawStakedQEURO / totalQEURO)
     │              │ hedgerShare = floor(grossStaker × haircutBps / 10000)
     │              ├──────────────────────────────────────────────▶│
     │              │ userShare = grossStaker - hedgerShare → QEURO credit (share price rises as yield vests)
     │              ├───────────────────────────────▶│              │
     │              │ treasuryShare = realizedYield - grossStaker (USDC) │              │
     │              ├──────────────────────────────────────────────▶│
     │              │ 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: _authorizeUpgrade requires the call to come from the configured timelock — on Base mainnet the 12 h OpenZeppelin TimelockController
  • 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:

  1. Deploy and verify the new implementation (run make check-verifiable-bytecode CONTRACT=<Name> first)
  2. Validate compatibility (make check-upgrade-safety: size, storage layout, ABI, version bump)
  3. SecureUpgradeable proxies: the Safe schedules upgradeToAndCall on the TimelockController, waits 12 h, then executes; plain-UUPS proxies: the Safe calls upgradeToAndCall directly
  4. Verify version() on the proxy and record it in deployments/{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: signed Hyperliquid reference read from SignedReferenceSource; normal signed age and additional adapter checks; independent Chainlink reference and USDC/USD validation
  • 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 IExternalStakingVault adapters (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

  1. Security First: All components designed with security as the primary concern
  2. Modularity: Clear separation of concerns and modular design
  3. Upgradeability: Future-proof design with upgrade capabilities
  4. Gas Efficiency: Optimized for cost-effective operations
  5. Transparency: Open and auditable code and processes

Development Principles

  1. Test-Driven Development: Comprehensive test coverage
  2. Documentation: Complete documentation for all components
  3. Code Review: Rigorous review process for all changes
  4. Continuous Integration: Automated testing and deployment
  5. Security Audits: Regular security assessments

This architecture document is maintained by Quantillon Labs and updated with each protocol version.

Oracle Architecture

Valuation and execution

Since 17 October 2026, signed reference reports supply the EUR/USD valuation path. SignedReferenceSource 1.0.0 checks the report signature, original observation time, sequence, epoch and independent Chainlink reference. HyperliquidEurUsdOracle 1.0.7 consumes that source in OracleRouter's active market slot 1. ChainlinkOracle in slot 0 remains a manual governance fallback and the USDC/USD source.

Reference valuation is separate from an exact execution quote. SignedExecutionPricing 1.1.0 validates transaction-specific execution authorization and signed hedge-capacity reports. A trade's size-dependent price does not change the valuation of all outstanding QEURO.

Data flow

Hyperliquid observation -> reference signer -> signed reference report
                                                | delivered with a transaction
                                                v
Chainlink independent reference ----------> SignedReferenceSource
                                                |
                                                v
                                      HyperliquidEurUsdOracle
                                                |
                                                v
                                           OracleRouter
                                                |
                                    Vault / HedgerPool accounting

Exact execution quote + capacity report -> SignedExecutionPricing -> settlement

SlippageStorage and the publication batchers are historical deployments; they no longer feed the active signed reference path. The adapter's slippageStorage() getter retains its legacy name but now returns SignedReferenceSource. The periodic publisher is retired.

Freshness and validity

Normal reference and capacity reports have a 60-second maximum age in the verified configuration. Execution quotes have a separate 45-second maximum measured from the original market observation. The adapter's 900-second market snapshot limit is an additional check, not permission to use an expired signed report or quote.

Report delivery preserves the original observation timestamp. Replaying an identical report cannot refresh it; an older report cannot overwrite a newer cached reference. Price bounds, independent-reference comparison, USDC validation and circuit breakers remain applicable. A rejected price is not made usable by returning a cached value with isValid = false.

The adapter supports the signed source's explicit emergency reference policy, with a configured age ceiling of 8100 seconds and the independent oracle's own validity checks. Emergency redemption has zero budget and is disabled in the current production configuration. Ordinary signed quotes cannot use this emergency age window.

Readiness during inactivity

A stored observation may age while no transaction needs it. Dashboards, keepers and the watchdog can obtain fresh signed reports and simulate their delivery with the relevant read or operation. Those simulations do not persist state and do not spend publication gas. An idle cache alone does not establish that signed delivery is unavailable.

The watchdog monitors fresh delivery and hedge health. Slow but successful probes are distinct from failed readiness checks. A valid signature establishes authorization, not economic accuracy or a completed Hyperliquid fill. Current state can still change between simulation and settlement.

Fallback and governance

OracleRouter selects one source; it does not automatically fail over. Switching to Chainlink is a governance action and does not, by itself, restore execution quotes, hedge capacity or a paused vault. Normal signed settlement fails closed when required data or authorization is unavailable.

Oracle proxies retain their peripheral administration and upgrade paths. The core controller and Safe have different responsibilities; a signed report grants no administrative role. Confirm live roles before constructing governance calls.

See Signed Quotes, Execution Pricing and Deployment Status for the verified release and user-facing behavior.

Signed Quotes in Production

Signed quotes were activated on Base mainnet (8453) on 17 October 2026. The confirmed governance execution is recorded at block 52,720,621. The production dapp reopened at 10:08 UTC after the coordinated contract and service cutover. The recurring market publisher is retired.

Versions and active bindings below were read at finalized Base block 52,727,379 on 17 October. These are dated observations; read the live contracts before integration.

ContractProxy or direct module addressVersion
QuantillonVault0x833E5Ba510a241b21F1C60c987D1c49eB52E4a071.6.0
UserPool0x712bCc77e7aa53C79870A40d044D440Ad2901bF21.3.0
HedgerPool0xff5D7cE5c7671B2EA805Ee752B4f8eC9Ecf2975A1.6.0
HyperliquidEurUsdOracle0x0B58aBB57775E0fCEDfd4460e00dD9D9610C2C431.0.7
SignedExecutionPricing0x076F86a591258957665b65c04F04B706D00EaEBa1.1.0
SignedReferenceSource0xFd059ed44959a6a7979e1485a825CE36Dc95cCB11.0.0

QuantillonVault.executionPricing() points to SignedExecutionPricing and signedExecutionEnabled() is true. The pricing module's referenceSource() and the market adapter's legacy-named slippageStorage() getter both point to SignedReferenceSource. OracleRouter still selects market slot 1. The pricing mode is NORMAL and the non-renewing emergency budget is 0 QEURO. The pricing module's active() getter describes a temporary settlement context, not whether signed execution is enabled.

See Production Protocol Reference for dated economic settings and Quick Start for the current integration path.

Three separate responsibilities

DataAuthorityOnchain consumer
Exact execution amountsExecution quote signerSignedExecutionPricing and the existing vault accounting
EUR/USD valuationReference signer, checked against an independent referenceSignedReferenceSource, market oracle and router
Hedge admissionCapacity signer, after venue and canonical Base reconciliationCumulative admission and acknowledgment counters

A trade's size-dependent execution rate must never revalue all outstanding QEURO. Signing amountOut does not bypass collateralization, protocol fees, execution spread, route validation or hedge-capacity limits.

Normal minting buys EUR exposure using asks. Redemption reduces that exposure using bids. The quote engine retains the reference clamps, walks the book with integer arithmetic and includes the configured execution buffer. The venue hedge follows Base settlement and remains non-atomic.

Contracts and entrypoints

SignedExecutionPricing and SignedReferenceSource are new non-upgradeable modules. QuantillonVault, UserPool and HedgerPool received governed implementation upgrades in this release. Linked settlement libraries must be included in deployment verification and bytecode-size checks.

The vault's existing configureExecutionPricing(address) detects the signed module. It still requires a paused vault, correct vault binding and no outstanding exposure in the previous module. The appended signedExecutionEnabled flag closes the old unquoted conversion paths. UserPool adds an appended route guard; existing deposit and withdrawal accounting runs with the original user.

EntrypointPurpose
QuantillonVault.executeWithQuote(bytes,bytes)One permitted vault operation with a signed authorization
UserPool.executeWithQuote(bytes,bytes)One pool deposit or withdrawal, retaining user tracking
HedgerPool.executeWithReference(bytes,bytes)Atomic reference delivery with enter, exit, remove-margin or emergency-close
QuantillonVault.emergencyRedeemQEURO(uint256,uint256)Explicitly governed, budgeted emergency redemption

The HedgerPool wrapper does not change ownership or roles. Add-margin stays available directly without a quote or reference signer. Delegated Safe/Zodiac callers use the typed removeMarginWithReference(uint256,uint256,bytes) route with scoped permissions. A signature does not grant caller authority.

Signature and calldata binding

Execution EIP-712 uses name Quantillon Execution, version 1, the deployment chain ID and the execution module as verifying contract. The quote includes:

address user;
address caller;
uint8 action;
uint256 amountIn;
uint256 amountOut;
uint256 observedAt;
uint256 validAfter;
uint256 validUntil;
uint256 nonce;
uint256 epoch;
bytes32 callHash;
bytes32 referenceHash;

callHash binds the complete inner calldata, including the route, vault ID and minimum shares when staking. Pool settlement binds caller to UserPool and user to the original wallet. Nonces are consumed per original user. Epoch changes invalidate outstanding execution authorizations; revoking a signer invalidates its signatures at settlement.

The authorization is ABI-encoded as (Quote,bytes,ReferenceReport,bytes,CapacityReport,bytes) inside the shared Authorization struct. Reference-only authorization is abi.encode(ReferenceReport, signature). The fixed wire vector is tested in both Node and Solidity for exact tuple encoding, signature recovery and chain-domain separation.

Reference signatures use domain name Quantillon Reference and the reference-source address. They carry price, original observation time, sequence and source epoch. Exact replay is idempotent; it cannot refresh the observation timestamp. An authenticated older report may accompany a still-valid quote, but it cannot replace a newer cached reference. Capacity reports carry cumulative acknowledged buys and sells, margin capacity, observation time, sequence, execution epoch and the canonical Base block/hash inspected by the signer.

Accounting and concurrency

For a mint, received USDC is split into protocol fees, reference-valued backing and execution spread. Token transfers, hedger synchronization, quote consumption and admission occur atomically. Failure rolls back all of them, including UserPool tracking and any report updates.

Out-of-order capacity delivery retains the latest accepted margin limit, original observation time and cumulative acknowledgments. All delivered signatures still require the authorized signer, current epoch, valid age and canonical block. Conflicting reports with the same sequence revert.

Exact output stays signed, while backing and reference-valued fees use the latest accepted reference. A quote can therefore fail current collateral or impact checks before its deadline; the deadline is an expiry bound, not an unconditional execution guarantee.

The signed module counts unresolved buys plus unresolved sells toward its gross admission limit. They do not cancel each other merely because their net exposure is zero. This is more conservative than the previous directional policy and must be included in capacity calibration.

Offchain reservations serialize all quote workers sharing a deployment. Reserved public order-book depth represents Quantillon's risk budget; it does not reserve liquidity on Hyperliquid. Release requires canonical nonce, epoch, time and settlement evidence. Unknown consumed nonces and reorganized settlements retain their budget.

Expiration and failure behavior

SignedExecutionPricing 1.1.0 enforces a forty-five-second maximum, measured from the original market observation. The matching API defaults to forty-five seconds. Production uses this forty-five-second limit. The module and reference source separately enforce a 60-second report-age limit; that does not extend a quote deadline. Issue age is bounded; the interface requires enough remaining time before opening the wallet. A quote can still expire during wallet interaction or inclusion. Approval precedes executable quote issuance.

Normal signed settlement fails closed on stale market data, invalid reference, exhausted capacity, bad signatures, expired authorization or pause. Emergency redemption is a separate mode, with a non-renewing budget and independent-reference checks. Switching modes alone does not replenish that budget. The existing market adapter's freshness policy also applies; emergency behavior must be rehearsed against the actual router and adapter.

Keeper yield conversion uses a distinct bounded-rate authorization because the exact harvested amount is known only during the transaction. The signed maximum must not be exceeded. Zero-harvest behavior, role checks, staking allocation and vesting must remain unchanged. Public quote issuance does not grant keeper authority.

Operations after activation

The paired dapp, quote/reference/capacity services, hedging engine, watchdog, dashboard and keeper consumers use the signed deployment. Required backend migrations and the reconciliation baseline were applied during maintenance before reopening. Fresh signed delivery is checked with read-only simulations; an idle cache alone does not require a paid publication transaction.

For a future upgrade, stage against actual deployed addresses, respect the controller's 12-hour delay and pause admission for binding changes and reconciliation. Timelock expiry does not execute an upgrade automatically. Keep admission closed if versions, signer authorization, references or hedge readiness do not match the reviewed release.

After signed settlements, a rollback must preserve transaction journals and reconcile real venue fills, consumed quotes and cumulative onchain admission. Restoring an old database or pointing to a legacy pricing module does not undo settlement.

Eliminating idle periodic publication removes its recurring gas expense. User settlement, governance, emergency actions and necessary operational acknowledgments still require transactions. No cross-chain fill guarantee is created by a signature.

Deploying a future inactive module

scripts/deployment/DeploySignedQuoteModules.s.sol deploys the reference and execution modules without changing any proxy, oracle binding or active pricing module. It requires the explicit environment/chain pair (dev/31337, preprod/31338, prod/8453), existing vault and independent-reference contracts, governance, reserve recipient and all risk bounds. Both modules are owned by governance from construction; the broadcaster receives no role. Execution remains paused and there are no authorized signing keys until governance configures them.

Before activation, governance must grant the reference signer on the source, grant the execution module the source's emergency-controller role, and grant separate execution and capacity signers on the pricing module. Bind the oracle adapter to the new reference source, upgrade the required vault/UserPool/HedgerPool implementations with their verified linked libraries, and check all bindings and roles against the release receipt. These operations belong to the governed cutover after old exposure is reconciled; module deployment alone does not satisfy that cutover.

The deployment script logs module addresses, not public Safe import payloads. Keep broadcaster receipts and any governed transaction staging artifacts in private operator storage. Do not run --broadcast as part of unit tests or documentation builds.

Historical preproduction validation (12 October 2026)

The integration passed direct mint/redemption, UserPool deposit/withdrawal, mint-and-stake share issuance, replay rejection, expiry rejection, signed keeper harvesting and a coordinated reset with fresh quote domains. Reference-backed dashboard and keeper previews use read-only simulation. A 70-second idle check confirmed no publisher transaction and no persistent reference update while valuation remained available. Hedge capacity remains simulated; no real Hyperliquid fill or production risk calibration is implied. Private installation receipts and keys are not published.

Historical production rehearsal and authority

The dedicated production candidate was rehearsed on a private Base fork pinned to block 52,554,188. The deployed TimelockController requires 43,200 seconds; execution before this delay was rejected. Vault 1.6.0, UserPool 1.3.0 and HedgerPool 1.6.0 were activated with their linked libraries, the signed reference source and signed pricing module. This is a migration rehearsal, not live deployment or a real Hyperliquid execution test.

The existing proxies assign operational GOVERNANCE_ROLE and EMERGENCY_ROLE to the Safe, while the timelock executes upgrades. Keep that division in the transaction plan. Initialize UserPool pending liabilities only when its explicit initialization flag is false. Preserve hedger cost-basis accounting.

The typed production Roles permission restricts removeMarginWithReference to position 1, a positive amount and CALL with no ETH. Dynamic reference bytes still require the pool's normal authorization checks. The paired backend verifies the exact permission event, storage and condition runtime; no generic reference-call permission is granted.

Before reopening admission, install the paired Dapp/services/watchdog release, initialize the immutable real-venue reconciliation baseline during the pause, and check the active module, source, signing authorities and signed readiness. There is no mandatory seven-day shadow window or completed-hedge quota. After activation, a software rollback must not silently replace contract bindings or discard signed settlements, journaled transactions or executed venue fills.

Public CI and private deployment entrypoint

The encrypted scripts/deployment/DeploySignedQuoteModules.s.sol entrypoint inherits the secret-free implementation in scripts/utils/SignedQuoteDeployment.s.sol. Tests import that implementation so an ordinary GitHub checkout can compile and validate environment guards and inactive deployments without the git-crypt key. No deployment credentials or transaction payloads are published.

Emergency freshness compatibility

The production release includes HyperliquidEurUsdOracle 1.0.7. Its ordinary market snapshot window is unchanged. In the governed signed source's explicit emergency mode it accepts that source's independent-reference age policy up to 8100 seconds. Original observation timestamps are preserved. Invalid or expired independent rounds still fail at the source; adapter bounds, reference comparison, USDC checks and circuit breakers still apply. A legacy source lacking the signed emergency getters cannot extend its snapshot window.

The configured emergency reference-age ceiling is 8100 seconds, subject to the independent oracle's own validity checks. This does not enable emergency redemption: the current emergency budget is zero. Any future activation requires governed configuration and validation through the source, adapter, router and vault. Normal quotes do not use this extended emergency window.

Signed Quotes: Historical Consolidation Record

Production activation completed on 17 October 2026. See Signed Quotes in Production. The dated candidate and rehearsal evidence below describes the preparation stage, not current deployment status.

Historical branch promotion — 13 October 2026

feat/signed-quotes-migration now contains the source and test changes validated on preprod through 08387433. The promotion preserves the original candidate history. It does not upgrade Base, change deployment manifests, send governance transactions or publish the production documentation site. Paired Dapp evidence is in docs/migrations/signed-quotes-production-sync-2026-10-13.md in the frontend repository.

Candidate versions are Vault 1.6.0, UserPool 1.3.0, HedgerPool 1.6.0 and ReferenceSettlementLibrary 1.1.0. The typed margin withdrawal and normal, paused, capacity-constrained, emergency and liquidation settlement tests are included. The six newly declared interface functions now have complete NatSpec. This documentation completion changes no runtime bytecode: canonical artifacts were compared before and after, and only matching-version dependency hashes were refreshed. No interface selector or storage field was changed by that completion.

Fresh validation: 186 tests across seven signed/reference suites; EIP-170, append-only storage, additive ABI, version tracing, 100% NatSpec and generated documentation checks. These are candidate checks, not production activation evidence.

Production preparation subsequently added live fill evidence/allocation, typed Roles permission support and private service/Dapp staging in the paired Dapp branch. An isolated Base fork at block 52,554,188 repeated deployment, the actual TimelockController's 43,200-second delay, refusal before eligibility and activation of these three proxy versions. The Safe performs operational pause and configuration; the timelock performs the upgrades. Existing UserPool pending liability initialization must be preserved rather than run a second time. No extra Solidity runtime change was needed for this backend preparation.

Before production activation, validate preprod, complete independent review and initial parameter/signer selection, deploy inactive production modules, stage artifacts against their actual addresses and submit the reviewed permissions and upgrade proposals. User decision on 13 October: no mandatory shadow duration or completed-hedge quota. Cut over services, Dapp and contracts with the explicit activation after the 12-hour governance delay, keeping admission closed until bindings and readiness are verified. Timelock expiry alone does not execute the upgrade. See docs/migrations/signed-quotes-production-preparation.md in the Dapp repository for the executable rehearsal and staged cutover sequence. Fork keys, mock feeds and fixture transaction artifacts must never be used on Base.

The historical preprod evidence below retains its original scope.


Signed quotes: preprod consolidation (2026-10-13)

Scope: the dedicated feat/signed-quotes-preprod branch. This change does not authorize a production or dev deployment.

Contract changes

HedgerPool 1.6.0 adds removeMarginWithReference(positionId, amount, authorization). It returns the underlying operation's ABI-encoded return data (empty for a successful withdrawal). The linked ReferenceSettlementLibrary 1.1.0 submits the governed signed reference and delegates the existing withdrawal in the same transaction. A failed withdrawal rolls back the reference update. The original caller, ownership, pause, reentrancy, margin and collateral checks remain in force. No storage field or namespace is added.

The typed selector exposes position and amount to Zodiac Roles conditions without granting the generic executeWithReference(bytes,bytes) wrapper. Existing generic reference operations remain supported for hedgers signing directly.

IHedgerPool and IQuantillonVault now declare their existing signed settlement entrypoints, in addition to the new typed withdrawal. The interfaces do not remove legacy selectors or economic guards. Removing the Dapp's legacy deviation input does not remove onchain reference bounds or execution impact limits.

Permissions and rollout

Preprod uses a local fork (chain 31338), with external capital execution disabled. Its governance impersonation is strictly local. Upgrade only HedgerPool; preserve pricing modules, signers, capacity counters, positions, and pause state. Record the implementation, library addresses, source commit and runtime hash privately. Keep the previous implementation for rollback; storage compatibility is unchanged.

Before enabling a Safe operator on any environment, governance must explicitly scope the typed selector to the correct pool and position, zero ETH value and CALL operation, retaining the reviewed amount policy. The authorization bytes contain only a reference report verified by the governed source. Do not grant arbitrary delegatecall or generic envelope permissions. Full Roles simulation must succeed before signing. The current production policy-history allowlist has not been migrated by this preprod change; it intentionally rejects unreviewed permission transitions.

Tests exercise the actual HedgerPool proxy against the reference source, including caller preservation, rejected callers, economic failure rollback, expired reports, and the preexisting margin-accounting suite. Safe client unit tests are not evidence that a live Safe permission upgrade has executed.

Verification

  • HedgerPool runtime: 24,534 bytes (EIP-170 limit: 24,576). There is little remaining headroom; future additions should use linked libraries.
  • Storage layout compared with the previous preprod artifact: identical after ignoring compiler AST identifiers.
  • Scoped upgrade rehearsed on an isolated fork of preprod (port 18550), retaining margin, exposure, oracle, pricing module, owner, time provider and pause state.
  • A real typed withdrawal of one USDC base unit succeeded on that isolated fork: total margin decreased by one and the owner's USDC balance increased by one. No test withdrawal was sent to the served preprod instance.
  • Three source-closure baselines (QuantillonRebalancerModule, YieldShift, YieldShiftOptimizationLibrary) were refreshed only after verifying their deployed bytecode was identical to the previous preprod artifacts. Interface additions changed dependency hashes without changing their runtime. The reference settlement library is now explicitly covered by the version gate.

Stateful preprod simulation (13 October, subsequent delivery)

The dedicated preprod branch now runs the normal hedging engine against a durable local venue. Orders, fills, fees, margin nonces and allocation to signed or emergency settlements survive worker restarts. The fork uses a sealed historical-origin cache; initialization may read the approved Base proxy, but ordinary sealed execution cannot. All transactions are on chain 31338. External orders and bridges remain disabled.

The served local Safe has a dedicated Roles module. Browser tests exercised a USDC collateral addition and the typed reference withdrawal, with exact Safe balance checks. This supersedes the earlier served-instance testing limitation above; it is not a production permission migration.

SignedProtocolSettlement.t.sol additionally covers pause/resume without nonce consumption, concurrent quotes against admitted capacity, emergency budget rollback, and pro-rata liquidation against the real router. Browser tests exercise emergency redemption with the quote signer stopped, liquidation redemption, stake/unstake and positive fixture-yield conversion followed by a simulated hedge and reconciliation. No contract bytecode was changed for these additional simulation tests, so the previously deployed versions remain Vault 1.6.0, UserPool 1.3.0 and HedgerPool 1.6.0.

Operational scenarios and reset instructions are in the Dapp repository at docs/migrations/preprod-isolated-simulation.md. Synthetic funding/APY data does not model Hyperliquid funding cashflows or exchange liquidations. Real-fill integration, initial parameter review and governed production activation remain separate release gates; no timed calibration window is required.

Shared candidate alignment — 14 October 2026

The preprod and production signed-quotes branches now share the same contract source, documented interfaces, deployment helper, version assertions and test CI. The synchronization changes no core implementation, storage layout or contract version. The eight signed/reference/version suites passed all 198 tests locally. The deployment entrypoint remains encrypted; the helper is testable in a locked checkout. This source synchronization does not upgrade either running instance.

Quantillon Protocol Security Guide

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

Overview

The Quantillon Protocol implements comprehensive security measures to protect user funds and ensure protocol integrity. This document outlines security best practices, the vulnerability disclosure process, and risk management guidelines.


Security Architecture

Multi-Layer Security Model

graph TB
    subgraph "Application Layer"
        AC[Access Control]
        RB[Role-Based Permissions]
        EM[Emergency Mechanisms]
    end
    
    subgraph "Smart Contract Layer"
        RP[Reentrancy Protection]
        OV[Overflow Protection]
        PA[Pause Mechanisms]
    end
    
    subgraph "Oracle Layer"
        CB[Circuit Breakers]
        PV[Price Validation]
        SF[Staleness Checks]
    end
    
    subgraph "Infrastructure Layer"
        UP[Upgradeable Proxies]
        TL[Timelock Controls]
        AU[Audit Trails]
    end
    
    subgraph "External Layer"
        AE[Internal AI-assisted Security Reviews]
        BB[Responsible Disclosure]
        MC[Monitoring & Alerting]
    end

Security Features

1. Access Control

Role-Based Access Control (RBAC):

  • Hierarchical permission system
  • Principle of least privilege
  • Time-locked upgrades: the eight SecureUpgradeable core proxies (QuantillonVault, QEUROToken, QTIToken, UserPool, HedgerPool, YieldShift, stQEUROFactory, stQEUROToken) can only be upgraded through the 12 h OpenZeppelin TimelockController
  • Multi-signature control: every privileged role is held by the 2-of-3 governance Safe. Parameter changes, and upgrades of the plain-UUPS FeeCollector / oracle / SlippageStorage proxies, execute as direct Safe transactions with no delay (see the governance-flow column of the 2026-08-26 bundle runbook)

Key Roles per contract:

// QEUROToken
MINTER_ROLE       = keccak256("MINTER_ROLE");      // Vault: mint QEURO
BURNER_ROLE       = keccak256("BURNER_ROLE");      // Vault: burn QEURO
PAUSER_ROLE       = keccak256("PAUSER_ROLE");      // Emergency: pause token, minting killswitch
COMPLIANCE_ROLE   = keccak256("COMPLIANCE_ROLE");  // Blacklist/whitelist management

// QuantillonVault / QTIToken / UserPool / HedgerPool / YieldShift / stQEUROFactory / stQEUROToken
GOVERNANCE_ROLE         = keccak256("GOVERNANCE_ROLE");         // Parameter updates, wiring
EMERGENCY_ROLE          = keccak256("EMERGENCY_ROLE");          // Emergency pause/withdraw
VAULT_OPERATOR_ROLE     = keccak256("VAULT_OPERATOR_ROLE");     // Vault: external-vault USDC deployment
YIELD_DISTRIBUTOR_ROLE  = keccak256("YIELD_DISTRIBUTOR_ROLE");  // Vault: harvestAndDistributeVaultYield / creditVaultYield
VAULT_FACTORY_ROLE      = keccak256("VAULT_FACTORY_ROLE");      // stQEUROFactory: vault self-registration
// HedgerPool has no hedger role: it uses a single-hedger allowlist (setSingleHedger)

// FeeCollector
GOVERNANCE_ROLE   = keccak256("GOVERNANCE_ROLE");  // Ratios, fund addresses, fee sources, upgrades (plain UUPS)
TREASURY_ROLE     = keccak256("TREASURY_ROLE");    // distributeFees
FEE_SOURCE_ROLE   = keccak256("FEE_SOURCE_ROLE");  // Contracts allowed to push fees

// OracleRouter / ChainlinkOracle / HyperliquidEurUsdOracle / StorkOracle / LighterEurUsdOracle (inert)
ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE"); // Feed/source updates, bounds, staleness, oracle switching
EMERGENCY_ROLE      = keccak256("EMERGENCY_ROLE");      // Circuit breakers, pause
UPGRADER_ROLE       = keccak256("UPGRADER_ROLE");       // Plain-UUPS upgrades (Safe direct, no timelock)

// SlippageStorage
MANAGER_ROLE        = keccak256("MANAGER_ROLE");        // Store configuration (sources, thresholds, intervals)
WRITER_ROLE         = keccak256("WRITER_ROLE");         // Publishing the venue mid on-chain

2. Reentrancy Protection

Implementation:

  • nonReentrant modifier on all state-changing functions
  • Checks-effects-interactions pattern
  • External call isolation
  • State variable protection

Example:

// OpenZeppelin ReentrancyGuardUpgradeable: a re-entrant call reverts with ReentrancyGuardReentrantCall()
function redeemQEURO(uint256 qeuroAmount, uint256 minUsdcOut) external nonReentrant whenNotPaused {
    // ... function logic
}

3. Oracle Security

Price Feed Validation:

  • Multiple price feed sources
  • Staleness checks (Hyperliquid: 15 min; Chainlink EUR/USD: 2 h; USDC/USD: 25 h)
  • Price bound validation
  • Circuit breaker mechanisms

The active deployment enforces a strict independent Chainlink EUR/USD reference check (enabled on 23 September 2026). Invalid, unavailable, stale or excessively divergent reference data blocks minting and normal redemption, including on weekends. The release must verify both successful operation with valid prices and rejection with an invalid reference. Configuration targets and live-state checks are documented in Oracle Architecture.

Implementation:

// QuantillonVault: an invalid oracle read is a hard stop for mint / redeem
(uint256 price, bool isValid) = oracle.getEurUsdPrice();
if (!isValid) revert CommonErrorLibrary.InvalidOraclePrice();

// Oracles: staleness, bounds and deviation checks return isValid = false instead of
// reverting; governance setters validate inputs with CommonErrorLibrary.InvalidPrice()

4. Emergency Mechanisms

Pause System:

  • Global pause functionality
  • Role-based pause controls
  • Contract-specific emergency controls; the vault has no generic emergency withdrawal from an external strategy
  • Circuit breaker activation

Implementation:

// OpenZeppelin PausableUpgradeable: `whenNotPaused` reverts with EnforcedPause()
function pause() external onlyRole(EMERGENCY_ROLE) {   // PAUSER_ROLE on QEUROToken
    _pause();                                          // emits Paused(msg.sender)
}

Responsible Disclosure

Reporting a vulnerability

Report suspected vulnerabilities privately to team@quantillon.money before any public disclosure. Include the affected contract(s) and addresses, a reproduction (preferably a Foundry test against a local fork) and your assessment of impact. The team acknowledges reports, works with the reporter on validation and remediation, and coordinates a reasonable disclosure date.

In scope: Quantillon-written contracts under src/ as deployed on Base mainnet (see the API Reference), including the oracle stack and external-vault integration logic. A defect in third-party code is outside this programme, but an exploitable impact caused by Quantillon's configuration or integration remains in scope.

Do not execute exploit or disruptive transactions on Base mainnet without prior written authorization. Do not access or move data or funds that are not yours, and do not perform denial of service, abusive automated traffic, oracle or market manipulation, governance interference, phishing, or social engineering.

The canonical, current terms and programme status are maintained at security.quantillon.money/disclosure. The disclosure programme is active and unpaid.

Audits

No professional security audit has been performed. Review to date is internal and AI-assisted; findings and corrections are ongoing work, not a completed audit milestone. Internal review does not establish that deployed contracts are free of defects. No external audit report is promised.


Risk Management

Risk Categories

1. Smart Contract Risks

Oracle Manipulation:

  • Risk: Price feed manipulation
  • Mitigation: Multiple price sources, circuit breakers
  • Monitoring: Price deviation alerts

Reentrancy Attacks:

  • Risk: State manipulation during external calls
  • Mitigation: Reentrancy guards, CEI pattern
  • Monitoring: Function call analysis

Access Control Bypass:

  • Risk: Unauthorized function execution
  • Mitigation: Role-based access control, multi-sig
  • Monitoring: Permission change alerts

2. Economic Risks

Liquidity Risk:

  • Risk: Insufficient liquidity for operations
  • Mitigation: Liquidity requirements, emergency procedures
  • Monitoring: Liquidity ratio tracking

Interest Rate Risk:

  • Risk: Adverse interest rate movements
  • Mitigation: Hedging mechanisms, rate limits
  • Monitoring: Rate change alerts

Market Risk:

  • Risk: Extreme market volatility
  • Mitigation: Circuit breakers, position limits
  • Monitoring: Volatility tracking

3. Operational Risks

Key Management:

  • Risk: Private key compromise
  • Mitigation: Hardware security modules, multi-sig
  • Monitoring: Access pattern analysis

Upgrade Risk:

  • Risk: Malicious or faulty upgrades
  • Mitigation: Timelock controls, governance
  • Monitoring: Upgrade proposal tracking
  • Version traceability: every core contract exposes IVersioned.version() and any change is traced through a semver bump (CI-enforced via make check-version-bump); deployments/{chainId}/versions.json records the live implementation + commit per contract, so an auditor can confirm exactly which source version is deployed (cast call <proxy> "version()(string)").
  • Controller authority: after bootstrap, setTimelock requires the current controller. The 23 September 2026 activation transferred core DEFAULT_ADMIN_ROLE to that controller and removed the Safe's direct default-admin role. Operational governance, pause and emergency roles remain with their existing holders. The handover is complete; read hasRole to confirm current authority.

Integration Risk:

  • Risk: Third-party protocol failures
  • Mitigation: Risk limits, emergency procedures
  • Monitoring: External protocol health

Security Best Practices

For Developers

1. Code Security

Input Validation:

function deposit(uint256 amount) external {
    if (amount == 0) revert CommonErrorLibrary.InvalidAmount();
    if (amount > MAX_DEPOSIT) revert CommonErrorLibrary.AboveLimit();
    // ... function logic
}

Access Control:

// Role checks use OpenZeppelin AccessControl (`onlyRole`) or the shared library helpers,
// which revert with custom errors (e.g. CommonErrorLibrary.NotGovernance / NotAuthorized)
function setParameter(uint256 value) external onlyRole(GOVERNANCE_ROLE) {
    // ... function logic
}

Reentrancy Protection:

function withdraw(uint256 amount) external nonReentrant {
    // ... function logic
}

2. Testing

Unit Testing:

  • Test all function paths
  • Test edge cases and boundary conditions
  • Test access control mechanisms
  • Test error conditions

Integration Testing:

  • Test contract interactions
  • Test external integrations
  • Test upgrade scenarios
  • Test emergency procedures

Fuzz Testing:

  • Random input generation
  • Property-based testing
  • Stress testing
  • Gas limit testing

3. Code Review

Review Checklist:

  • Access control implementation
  • Input validation
  • Reentrancy protection
  • Error handling
  • Gas optimization
  • Event emission
  • Documentation

For Integrators

1. Integration Security

Contract Verification:

// Verify contract addresses
const VAULT_ADDRESS = "0x..."; // Verified on Etherscan
const QEURO_ADDRESS = "0x..."; // Verified on Etherscan

// Verify contract state
const isPaused = await vault.paused();
if (isPaused) {
    throw new Error("Contract is paused");
}

Transaction Security:

// Use slippage protection
const slippage = 0.05; // 5%
const minOutput = expectedOutput * (1 - slippage);

// Validate transaction parameters
const gasEstimate = await contract.estimateGas.function(params);
const gasLimit = gasEstimate.mul(120).div(100); // 20% buffer

Error Handling:

try {
    await contract.function();
} catch (error) {
    const msg = error.reason || error.message;
    if (msg.includes('InsufficientBalance') || msg.includes('ERC20InsufficientBalance')) {
        // Handle insufficient balance
    } else if (msg.includes('InvalidOraclePrice')) {
        // Handle stale / invalid oracle price
    } else if (msg.includes('EnforcedPause')) {
        // Handle paused contract
    } else {
        // Handle other errors
    }
}

2. Monitoring

Event Monitoring:

// Monitor important events (QEUROminted: lowercase m, 3 arguments)
vault.on('QEUROminted', (user, usdcAmount, qeuroAmount) => {
    console.log(`User ${user} minted ${qeuroAmount} QEURO`);
});

// Pause is the OpenZeppelin Pausable event
vault.on('Paused', (account) => {
    console.log(`Contract paused by ${account}`);
});

Health Checks:

async function healthCheck() {
    const [isPaused, [price, isValid], collateralizationRatio, mintFloor, criticalRatio] = await Promise.all([
        vault.paused(),
        oracleRouter.callStatic.getEurUsdPrice(),   // non-view: simulate instead of sending a tx
        vault.getProtocolCollateralizationRatio(),   // 18-decimal percent, 1e20 == 100% (0 while nothing is minted)
        vault.minCollateralizationRatioForMinting(), // 1.025e20 live (102.5%)
        vault.criticalCollateralizationRatio()       // 1.01e20 (101%)
    ]);

    if (isPaused) {
        console.warn("Vault is paused");
    }

    if (!isValid) {
        console.warn("Oracle price is stale or invalid");
    }

    if (collateralizationRatio.lt(mintFloor)) {
        console.warn("Protocol CR below the minting floor: mints are refused");
    }

    if (collateralizationRatio.lte(criticalRatio)) {
        console.error("Protocol CR at or below the critical ratio: liquidation-mode redemptions");
    }
}

Incident Response

Response Procedures

1. Detection

Automated Monitoring:

  • Price deviation alerts
  • Liquidity threshold alerts
  • Access control violation alerts
  • Unusual transaction pattern alerts

Manual Monitoring:

  • Community reports
  • Security researcher reports
  • Internal security reviews
  • External audit findings

2. Assessment

Severity Classification:

  • Critical: Immediate threat to user funds
  • High: Significant risk to protocol integrity
  • Medium: Moderate risk with workarounds
  • Low: Minor issues with minimal impact

Impact Analysis:

  • Affected contracts and functions
  • Potential financial impact
  • User impact assessment
  • Recovery time estimation

3. Response

Immediate Actions:

  • Activate emergency pause if necessary
  • Notify security team and stakeholders
  • Assess and contain the issue
  • Implement temporary mitigations

Recovery Actions:

  • Develop and test fixes
  • Deploy fixes through governance
  • Monitor system recovery
  • Conduct post-incident review

4. Communication

Stakeholder Notification:

  • Internal team notification
  • Community announcement
  • Partner notification
  • Regulatory notification (if required)

Transparency:

  • Incident timeline
  • Root cause analysis
  • Remediation steps
  • Prevention measures

Security Monitoring

Real-Time Monitoring

Key Metrics:

  • Contract pause status
  • Oracle price staleness
  • Liquidity ratios
  • Access control changes
  • Unusual transaction patterns

Alerting:

  • Price deviation > 5%
  • Protocol collateralization ratio below the governance-set minting floor (minCollateralizationRatioForMinting: 105% at launch, 102.5% under the September 2026 margin policy; liquidation mode at <= 101%)
  • Emergency role activation
  • Large transaction volumes
  • Failed transaction spikes

Security Dashboards

Operational Dashboard:

  • System health indicators
  • Performance metrics
  • Error rates
  • Gas usage patterns

Security Dashboard:

  • Access control events
  • Emergency activations
  • Oracle health status
  • Risk metrics

Security Contacts

Primary Contacts

Security contact: team@quantillon.money — vulnerability reports and responsible disclosure (see Responsible Disclosure)


Security Resources

Documentation

Tools

Security Analysis Results

Use generated artifacts from each run instead of hardcoded snapshots:

  • scripts/results/slither/slither-report.txt
  • scripts/results/slither/slither-report.json
  • scripts/results/mythril-reports/
  • scripts/results/natspec-validation-report.txt
  • scripts/results/contract-sizes/contract-sizes-summary.txt

Running Mythril Analysis:

# Run Mythril analysis
make mythril

# Or run directly
./scripts/run-mythril.sh

# Run Slither static analysis
make slither

# Validate NatSpec coverage
make validate-natspec

# Run EIP-170 contract size checks
make analyze-contract-sizes

# Run comprehensive security analysis (Slither + Mythril)
make security

This security guide is maintained by Quantillon Labs and updated regularly.

Operational invariants for minting and yield

Public minting continues to use the configured mint floor. Yield conversion is independent and is permitted only when current collateralization is strictly above max(101%, criticalCollateralizationRatio) and projected collateralization is at least 100%. The final QEURO token mint remains authoritative for pause, killswitch, cap, whitelist, blacklist, and rate-limit checks; failed token or hedger checks revert atomically, preserving the harvest for retry.

Accepted operational-scope risks

This remediation release preserves the current publisher and Safe Roles assignments, including the existing shared publisher/reporting identity, operational FeeCollector recipients, and Zodiac Roles module permissions. It does not rotate the publisher key, split those identities, replace recipients, or remove the existing Zodiac permissions. These remain separately governed operational risks; the contract safeguards and monitoring in this release do not change those assignments.

Quantillon Protocol — Deployment Guide

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

For the current deployed behavior, versions and role ownership, use Production Protocol Reference. Dated release sections below describe their respective upgrade bundles, not the latest state after subsequent upgrades.

Current Base release: 17 October 2026

The signed-quote migration is active. The confirmed governance execution upgraded the core implementations and configured the signed deployment. At finalized block 52,727,379, the live versions are Vault 1.6.0, UserPool 1.3.0, HedgerPool 1.6.0, HyperliquidEurUsdOracle 1.0.7, SignedExecutionPricing 1.1.0 and SignedReferenceSource 1.0.0. The current emergency budget is 0 QEURO.

The production dapp and affected services were cut over during maintenance and reopened at 10:08 UTC. The periodic publisher is retired. See Signed Quotes in Production for active addresses, bindings and integration requirements. September release sections below are historical records; their publisher commands and addresses do not describe the current signed deployment.

Overview

This guide covers deploying and configuring the Quantillon Protocol smart contracts using Foundry. Core contracts are deployed in a single forge script invocation via DeployQuantillon.s.sol, which writes the deployed addresses to deployments/{chainId}/addresses.json.


Versioning & Provenance

Every core contract implements IVersioned.version() — a pure semver getter that, read through the proxy, reflects the deployed implementation. Linked libraries expose version(); inlined libraries carry a VERSION constant.

Golden rule — every change is traced through a version bump. Any change to a deployed contract or library (correction, bug fix, update, or upgrade) MUST bump its version() per semver:

  • PATCH (1.0.0 → 1.0.1): bug fix or internal-logic change.
  • MINOR (1.0.0 → 1.1.0): new function or externally-observable behavior (ABI-additive).
  • MAJOR: reserved — storage-layout / ABI breaks are disallowed by the upgrade-safety gates.

This is enforced in CI by make check-version-bump: it hashes each versioned unit's import closure (deterministic, build-independent) and fails if a source dependency changed without a version() bump — comment and NatSpec edits count as changes. After an intentional bump, re-baseline with scripts/check-version-bump.sh --update (commits the new hash+version to version-baseline/).

Deployed-version manifest. deployments/{chainId}/versions.json records verified deployments. Upgrade scripts write receipt-backed entries after a completed proxy upgrade; a later reconciliation can record finalized implementations, versions and runtime hashes without claiming an unverified deployment timestamp. Live implementation slots, version() values and bindings are authoritative. Candidate-only actions (deploy-only, propose, and approve) leave it unchanged. Pass GIT_COMMIT=$(git rev-parse HEAD) to the upgrade scripts so the commit is recorded.

Answering "what is deployed / what needs upgrading?"

# On-chain: read the live implementation's version directly
cast call <proxy> "version()(string)" --rpc-url $RPC_URL

# Report deployed-vs-source for every contract (flags which need an upgrade)
make check-deployed-versions

# One-time seed of versions.json for contracts deployed before versioning existed
RPC_URL=$RPC_URL GIT_COMMIT=<sha> scripts/deployment/backfill-versions.sh 8453

Basescan verifiability — check BEFORE every implementation deploy. Under via_ir, a contract's optimized bytecode can depend on the full compilation unit, while forge verify-contract submits a standard-json pruned to the contract's dependency closure — if the two compiles diverge, the deployed implementation can never be verified (QuantillonVault v1.1.1, 2026-07-04; ~67 bytes of drift). Whether a given contract/version diverges is per-compile luck, so gate every impl:

# ok  -> deploy normally (UpgradeBase deploy-only); standard verification will match
# FAIL-> deploy the pruned-unit bytecode instead, so verification matches by construction
make check-verifiable-bytecode CONTRACT=QuantillonVault

# On FAIL: same sources & settings, equally valid compile — but reproducible by the verifier.
# Requires CAST_ACCOUNT, RPC_URL, RELEASE_MANIFEST and private VERIFIABLE_OUTDIR.
# Uses a Foundry keystore; raw keys never enter cast arguments. Continue the
# Safe/timelock flow with the verified implementation address.
scripts/deployment/build-verifiable-impl.sh QuantillonVault \
  --lib src/libraries/StakingYieldLibrary.sol:StakingYieldLibrary=<addr> \
  --lib src/libraries/TreasuryRecoveryLibrary.sol:TreasuryRecoveryLibrary=<addr> \
  --deploy

Base deployment reconciliation — September 20, 2026

HedgerPool 1.3.0 is active at proxy 0xff5D7cE5c7671B2EA805Ee752B4f8eC9Ecf2975A, using implementation 0x8d83F7463CbFfd188Df7bC4302900151e273435a and HedgerPoolAccountingLibrary 1.1.0 at 0x4FDA47d379f00f849808500DD52b5106825ce5f1. Both implementations were deployed at Base block 51,522,127. The pool upgrade and one-time legacy correction executed together at block 51,548,748, September 20 at 06:47:23 UTC, in the completed Safe transaction.

The correction assigned 0.388448 USDC of existing unallocated backing to the current Safe hedger position's margin without transferring tokens or minting QEURO. The correction marker is already set; this is a record of completed execution, not a pending operation. The reconciled source and regression tests are recorded in commit 37d2381fbe0ed73bc28160fa46d335f6a73de265 (committed after deployment).

The same reconciliation corrected the stale QuantillonVault manifest entry to 1.2.1, implementation 0xdA2eF3B9CCD2b819806b29A5Ac65abCf689E2227, activated at block 51,202,101 on September 12 at 06:12:29 UTC in its existing upgrade transaction. The source is commit 03d8120181ea919dddc3ea7cd203b4793e0999cf; no new vault upgrade was performed.

For all three units, a fresh Solidity 0.8.24 verification-unit build (via_ir, optimizer runs 0) reproduced the complete deployed runtime after applying the live library addresses and constructor immutables, checked at block 51,571,753. The manifest records the runtime code hashes and separates implementation deployment from proxy activation. All 31 hedger accounting/correction regression tests passed, including the pinned Base fork; ABI, storage layout, contract size, and version checks passed.

HedgerPool remaining-cost accounting activation

HedgerPool v1.1.0 values filledVolume as the original USDC cost of the remaining QEURO backing. Deploy its implementation with HedgerPoolLogicLibrary v1.0.1 and HedgerPoolRedeemMathLibrary v1.0.1. Fresh proxies activate this model in initialize. Build and verify with FOUNDRY_PROFILE=production (optimizer_runs = 0), using an isolated output/cache directory when test builds are running concurrently.

An existing proxy requires settlement before upgrading: position 1 must be inactive, totalMargin, totalExposure, and totalFilledExposure must be zero, and the vault's totalMinted() must be at most QEURO_DUST_THRESHOLD. Reconcile the position and vault balances before closure; this upgrade does not convert an active position's balances.

After settlement, pause the pool through EMERGENCY_ROLE, execute the implementation upgrade through the configured timelock, and call initializeCostBasisAccounting() through GOVERNANCE_ROLE while the pool remains paused. Verify costBasisAccountingInitialized() == true before unpausing. Installing the implementation alone leaves mint/redeem accounting, margin changes, normal exits, and effective-collateral queries blocked until activation. The generic upgrade script does not perform this governance activation call.

Base release (23 September 2026, historical)

The live versions and runtime hashes are recorded in deployments/8453/versions.json. Proxy addresses are unchanged. The coordinated activation completed on Base at block 51,685,734 on 23 September 2026, 10:53:35 UTC. The controller operation is complete. Versions at that activation were QEUROToken 1.0.9, QTIToken 1.0.5, UserPool 1.0.6, HedgerPool 1.4.1, stQEUROFactory 1.0.4, YieldShift 1.1.1, ChainlinkOracle 1.0.5, OracleRouter 1.1.2, SlippageStorage 1.0.3, LighterEurUsdOracle 1.0.2 (inert), and FeeCollector 1.0.3. QuantillonVault 1.3.4, per-vault stQEUROToken 1.2.4, HyperliquidEurUsdOracle 1.0.5, and ExecutionPricing 1.3.2 retain their existing implementations. The factory now uses the 1.2.4 staking-token template for future series. The vault links ExecutionPricingLibrary 1.1.1, StakingYieldLibrary 1.3.2, TreasuryRecoveryLibrary 1.0.1, and SecureUpgradeLibrary 1.0.1.

ComponentCurrent address
ExecutionPricing0xFA894CD2e0C8030c95925FfF3b8206F397e0D897
PublicationBatcher (price/depth)0xFB9C8Bb7003e8b4E2F158ee8F72eCdA38A81c9AE
ReportPublicationBatcher (active publisher route)0xBdd672FB97ecC9f5c8eBcD783a2Fe1234cA1a5FB

VaultId 2 now uses MetaMorphoStakingVaultAdapter 2.1.1 at 0x4c9B8b09214d37D5310b8E6768cF28E0dDcEDC30; principal and uncredited yield were transferred atomically, and temporary migration permissions were revoked. The eight existing secure proxies have controller default-admin authority with Safe operational roles preserved. Strict reference limits are 200/300 bps with 8,100 seconds maximum age; cumulative price drift is 100 bps / 3,600 seconds. The public mint floor remains 102.5%. Yield conversion has its own CR gate and still requires token eligibility, execution liquidity and hedger capacity; an unsuccessful harvest rolls back for retry.

QuantillonVault.executionPricing() is authoritative for the active module. The local, gitignored deployments/8453/addresses.json and dapp src/config/addresses.json must agree with it. Preserve the zero-address stQEUROToken placeholder in those registries: resolve each live token through the factory; the manifest records the vaultId-2 proxy explicitly.

Before switching publisher configuration, verify writer(), priceStore(), and depthStore() on the selected batcher. The active ReportPublicationBatcher needs all three grants: SlippageStorage WRITER_ROLE, ExecutionPricing WRITER_ROLE, and ExecutionPricing REPORTER_ROLE. A grant to PublicationBatcher or the publisher EOA does not confer permission on ReportPublicationBatcher. Set EXECUTION_PRICING_ADDRESS, PUBLICATION_BATCHER_ADDRESS, and REPORT_PUBLICATION_BATCHER_ADDRESS to the same deployment generation. Append both new batcher-to-module mappings to the indexer's PUBLICATION_BATCHERS; retain historical mappings for decoding older events.

Verify accepted price, book and capacity events on chain, fresh observations, usable mint/redeem previews, token state and hedger reconciliation before opening the vault. Execution depth and capacity expire after 60 seconds on this module; the batch heartbeat is min(PUBLISHER_INTERVAL_S, maxAge / 2) (30 seconds with the 60-second publisher interval). Partial price/depth reports may restore oracle health before capacity can be certified. Health endpoints alone do not prove that all reports were accepted. If the watchdog owns a pause, let its configured recovery checks complete before resuming operation.

Coordinated core implementation release

Treat a coordinated release as one reviewed package with two mandatory governance steps: schedule the complete timelocked batch, then activate all components in one atomic Safe transaction after the controller's live minimum delay. Direct-Safe oracle and fee upgrades can share that activation transaction with the timelock execution, configuration calls and adapter migration. Scheduling must not change runtime addresses or pause production. Execution time is measured from the confirmed scheduling block, not proposal submission.

The active release includes the strict Chainlink EUR/USD cross-check: setReferenceCheck(200, 300, 8100), after upgrading the independent reference probe. Verify all three values after execution and test that stale, unavailable and divergent references reject minting and normal redemption. This applies on weekends too; there is no stale-reference bypass. See Oracle Architecture.

Inventory factory implementation templates and every registered staking series separately from the factory proxy. Update the template even when existing series already use the desired token implementation. Include funded non-upgradeable adapters using the atomic migration procedure. The retired Stork proxy, standalone production time provider and OpenZeppelin controller are not automatically upgrade targets for similarly named source contracts; verify their actual deployment type and active consumers first.

Rehearse the exact Safe hashes, all implementation slots and runtime hashes, library links, temporary role revocation, retained yield and unchanged supply, collateral and hedger accounting. Test the dapp's mint, redeem, stake and withdrawal paths plus keeper harvesting against the upgraded state. An isolated time-warped governance rehearsal proves delay enforcement; it cannot certify live report freshness. Repeat fresh-price integration checks separately and recheck production readiness before executing the queued package.

Deploy the coordinated core implementations from the release manifest. Read target versions from version-baseline/ and live versions.json; do not reuse the historical version list in older runbooks. Link the vault using the library addresses recorded for its selected implementation in versions.json; preserve the pool library links recorded for that release. Preserve each implementation's existing TimeProvider constructor argument. Check the factory registry for all token proxies; the zero stQEUROToken entry in addresses.json is not an upgrade target.

The base timing helper uses block.timestamp; contracts with a TimeProvider read that provider directly. Before upgrading, check the provider's offset and ensure no emergency-disable proposal spans a change of clock.

For the Base controller, schedule all implementation upgrades with TimelockController.scheduleBatch from the governance Safe. Read getMinDelay() and wait for readiness. The Safe's execution batch must pause vault and pool, execute the timelocked implementation upgrades, perform explicitly listed governance activation, and unpause only after post-upgrade checks pass. For every existing stQEURO proxy, keep the vault paused and call syncVesting() immediately after the implementation upgrade. Verify the YieldVestingSynced event, totalAssets() <= asset balance, and the expected accounted/unvested balances from the implementation state before allowing deposits or unpausing. A plain upgradeToAndCall(newImpl, "") does not run the token initializer, so omitting this sync exposes historical donations through the first read path.

Installing QuantillonVault v1.2.0 leaves executionPricing() at zero on an existing proxy. This installs pricing support while retaining reference-price settlement. Pricing can be activated in the same release by deploying a vault-bound module with explicit writer/reporter addresses, reserve recipient and risk limits. Configure the publisher and hedge reporter against that module before execution. Align report freshness, hedge tolerance and execution-impact limits with the hedge engine. Both depth and capacity reports must remain fresh through the upgrade window.

For coordinated pricing activation, add the Safe's call to QuantillonVault.configureExecutionPricing(module) after P&L activation and before unpausing. Check that the module has fresh depth, reconciled hedge exposure, positive executable capacity and usable previews before enabling settlement. An implementation upgrade alone does not activate the pricing module.

Rehearse the exact staged bytecode and controller calls on a pinned Base fork with scripts/deployment/DryRunCombinedRelease.s.sol. Its deployment input contains library link offsets, constructor arguments and the seven proxy addresses; the script never broadcasts. Independently validate storage, ABI, versions, runtime size and reproducible verification inputs before deploying implementations.

Execution-pricing launch configuration

The combined Base release activated on 11 September 2026 at 06:54:31 UTC in the Safe execution transaction. That launch used 0x57fBdf17a55D8F1d89E244D8D88937a867FfD063; the current module is listed in Current Base release. The following launch configuration is recorded in deployments/8453/execution-pricing-candidate.json; the active module's getters remain the source of truth for current values. Verified deployed versions are recorded in deployments/8453/versions.json.

SettingSelected valuePurpose
Maximum depth/account age60 secondsReject stale book or margin observations; the execution publisher refreshes on the 10-second polling loop when due.
Maximum execution impact25 bps (0.25%)Total per-level price limit relative to the reference oracle, consistent with the hedge engine's existing limit.
Execution buffer0 bpsCurrent governance-selected value. It remains changeable through updateRiskLimits while the vault is paused and admitted exposure is settled.
Maximum unacknowledged exposureEUR 1,000Aggregate across mint and redeem directions; additionally limited by current depth and reporter-certified margin capacity.
Published depthUp to 10 observed levels per sideKeeps cold publication within the writer's existing gas ceiling; omitted depth never contributes to capacity.
Base confirmations for reporting4 blocksReporter uses confirmed supply and admission counters and checks the block hash again.
Hedge acknowledgment toleranceEUR 1Matches the engine's existing target tolerance; bounds residual exposure, rather than asserting an exactly matched hedge.
Writer and reporter0xC57bF47310897B49aa72503AE568Fa46f2a5E008Existing publisher; both roles use its single durable transaction journal.
Spread reserve recipient0x8DAD1B6c1A40e2649d50952977b5af1992f098d1Existing hedge-funding account; governance withdrawals pay this fixed recipient.

The reporter permits at most one wei of difference between the engine's indexed target and confirmed QEURO supply to accommodate the residue after full redemption. This bookkeeping tolerance is separate from the EUR 1 actual hedge-exposure check.

At selection, the unified Hyperliquid account held approximately 108.43 USDC. EUR 1,000 at the observed 1.16355 reference price requires approximately 23.27 USDC of margin at the engine's existing 50x leverage, before its 1 USDC cushion. This is a launch ceiling, not an assertion that this capacity is always available. The reporter reduces admission as available funding decreases; no additional leverage is enabled by this configuration.

The observed xyz:EUR market had growth mode enabled and deployer fee scale 1. With the account's 0.045% base taker rate and no referral discount, the documented fee formula gives approximately 0.009% (0.9 bps), before any aligned-collateral discount. Fees and market conditions can change; the buffer does not guarantee a hedge fill. See Hyperliquid's fee formula.

ExecutionPricing v1.1.0 lets governance update age, impact, buffer and the exposure ceiling through updateRiskLimits(age, impact, buffer, outstandingLimit). The vault must be paused and outstanding admission must be zero. The update invalidates both depth and capacity; new reports must carry source timestamps strictly after the update. Keep settlement paused until those reports restore usable quotes.

The admin Parameters tab provides editable inputs, validates contract bounds and generates the governance Safe transaction. It displays release settings separately from live on-chain values and quote status. The reserve recipient remains fixed; changing that address requires replacing the module. Publisher confirmations and hedge tolerance are service configuration, separate from the four contract limits.

LighterEurUsdOracle (historical — venue not adopted)

LighterEurUsdOracle was deployed on 2026-07-17 as the candidate market oracle for a second hedge venue and most recently upgraded to 1.0.2 on 2026-09-23; on 2026-09-01 the Lighter venue was ruled out for good, so the proxy stays deployed and inert (no router slot, no consumer) as a historical record and no activation is planned. Like the other oracle proxies it is plain UUPS controlled by UPGRADER_ROLE (Safe direct, no timelock), and its upgrade script (scripts/deployment/UpgradeLighterOracle.s.sol, UPGRADE_ACTION=deploy-only then record) follows the pattern described above — kept only so the inert deployment can be maintained if ever required.


Prerequisites

Required Tools

  • Foundry (forge, cast, anvil): curl -L https://foundry.paradigm.xyz | bash && foundryup
  • jq: for post-deployment address parsing (sudo apt install jq or brew install jq)
  • Node.js 18+ (for NatSpec validation and size analysis scripts)

Environment File

Copy the appropriate template and fill in your values:

# Localhost development
cp .env.localhost .env

# Base Sepolia testnet
cp .env.base-sepolia .env

# Base mainnet production
cp .env.base .env

Required variables:

VariableDescription
PRIVATE_KEYDeployer private key
ETHERSCAN_API_KEYBaseScan API key (needed for --verify)

Optional variables (default to deployer address if not set):

VariableDescription
TREASURYFeeCollector treasury wallet
DEV_FUNDFeeCollector dev fund wallet
COMMUNITY_FUNDFeeCollector community fund wallet
SINGLE_HEDGERInitial single hedger address on HedgerPool
USDCUSDC address override (auto-selected by network if not set)
STORK_CONTRACT_ADDRESSStork oracle contract override

Deployment Architecture

DeployQuantillon.s.sol deploys all contracts in this dependency order within a single broadcast session:

TimeProvider
    └── ChainlinkOracle (or MockChainlinkOracle) + ERC1967Proxy
    └── StorkOracle (or MockStorkOracle) + ERC1967Proxy
    └── OracleRouter + ERC1967Proxy
            │
            ├── FeeCollector + ERC1967Proxy
            │       └── QEUROToken + ERC1967Proxy
            │               └── QuantillonVault + ERC1967Proxy
            │
            ├── QTIToken + ERC1967Proxy
            │
            ├── UserPool + ERC1967Proxy
            ├── HedgerPool + ERC1967Proxy
            ├── YieldShift + ERC1967Proxy
            ├── stQEUROToken (implementation)
            └── stQEUROFactory + ERC1967Proxy
                    └── _wireContracts() — configures dependencies/roles and enforces required post-deploy wiring (no vault registration)

After deployment, addresses are written to deployments/{chainId}/addresses.json.

Required post-deploy wiring now enforced in-script (deployment reverts if any check fails):

  • quantillonVault.initializePriceCache()
  • yieldShift.configureDependencies(...)
  • yieldShift.bootstrapDefaults()
  • hedgerPool.configureDependencies(...) (includes feeCollector)
  • feeCollector.authorizeFeeSource(quantillonVault)
  • feeCollector.authorizeFeeSource(hedgerPool)

Vault registration is intentionally deferred: DeployQuantillon.s.sol does not register any stQEURO vault token or adapter on initialization. Use scripts/deployment/setup-external-vaults.sh for post-core onboarding.

Network Configuration

NetworkChain IDUSDCStork (deploy-script input; parked on mainnet)Chainlink EUR/USD
Localhost (Anvil)31337Base mainnet USDC or MockUSDCMockMock (or real on fork)
Base Sepolia845320x036CbD53842c5426634e7929541eC2318f3dCF7eMock0xd30e2101a97dcbAeBCBC04F14C3f624E67A35165
Base Mainnet84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA029130x647DFd812BC1e116c6992CB2bC353b2112176fD60xc91D87E81faB8f93699ECf7Ee9B44D11e1D53F0F

Production oracle stack. DeployQuantillon.s.sol deploys ChainlinkOracle, StorkOracle and OracleRouter. The market oracle originally used SlippageStorage + HyperliquidEurUsdOracle (router slot 1, active since 2026-06-25); since 17 October 2026 its source is SignedReferenceSource. The original components were deployed by dedicated scripts under scripts/deployment/ (DeployHyperliquidOracle.s.sol for the oracle) and wired into the router by the Safe (updateOracleAddresses, then switchOracle(1)). StorkOracle is parked on mainnet. See Oracle Architecture.


Localhost Deployment

Start Anvil

# Plain local node (all mocks required)
anvil --host 127.0.0.1 --port 8545 --accounts 10 --balance 10000

# Or fork Base mainnet (allows using real oracle feeds without mocks)
anvil --host 127.0.0.1 --port 8545 --fork-url https://app.quantillon.money/api/rpc/base --chain-id 31337

Deploy

# All mocks (MockUSDC + MockChainlinkOracle + MockStorkOracle)
./scripts/deployment/deploy.sh localhost --with-mocks

# Mock oracle only (real USDC from fork)
./scripts/deployment/deploy.sh localhost --with-mock-oracle

# No mocks (assumes Base mainnet fork with real contracts)
./scripts/deployment/deploy.sh localhost

Output

deployments/31337/addresses.json

Testnet Deployment (Base Sepolia)

# With mock contracts (recommended for testing)
./scripts/deployment/deploy.sh base-sepolia --with-mocks --verify

# With real Chainlink feeds + real USDC
./scripts/deployment/deploy.sh base-sepolia --verify

The script automatically:

  • Sets gas price to 2 gwei
  • Uses --slow to send transactions one-at-a-time (avoids nonce desync with public RPCs)
  • Polls for stable nonce before broadcasting

Output

deployments/84532/addresses.json

Mainnet Deployment (Base)

Pre-Deployment Checklist

Before deploying to Base mainnet:

  • Set TREASURY, DEV_FUND, COMMUNITY_FUND to governance-controlled multisig addresses in .env.base
  • Set SINGLE_HEDGER to the authorized hedger address
  • Verify PRIVATE_KEY belongs to a dedicated deployment wallet with sufficient ETH
  • Set ETHERSCAN_API_KEY for contract verification
  • Run a dry-run first: ./scripts/deployment/deploy.sh base --dry-run
  • Test on Base Sepolia with the same configuration

Deploy

# Production deployment with verification and the size-minimising production profile
./scripts/deployment/deploy.sh base --verify --production

The --production flag sets FOUNDRY_PROFILE=production, which compiles with optimizer_runs = 0 (defined in foundry.toml): runtime bytecode is minimised to stay under the EIP-170 limit (via_ir is on in every profile; the test/coverage profiles use 200 runs).

Output

deployments/8453/addresses.json

Dry Run

Test the deployment without broadcasting any transactions:

./scripts/deployment/deploy.sh localhost --dry-run
./scripts/deployment/deploy.sh base-sepolia --dry-run
./scripts/deployment/deploy.sh base --dry-run

Post-Deployment

deploy.sh automatically runs these after a successful deployment:

1. Copy ABIs to Frontend

./scripts/deployment/copy-abis.sh localhost

Copies all contract JSON artifacts from out/ to the path specified in FRONTEND_ABI_DIR.

2. Update Frontend Addresses

./scripts/deployment/update-frontend-addresses.sh localhost

Reads deployments/{chainId}/addresses.json and writes the frontend addresses.json to FRONTEND_ADDRESSES_FILE.

3. Onboard External Vaults (Required for Multi-Vault Staking)

Core deploy does not set adapter routing/defaults. Onboard vaults with:

./scripts/deployment/setup-external-vaults.sh \
  --rpc-url http://localhost:8545 \
  --private-key "$PRIVATE_KEY" \
  --quantillon-vault 0xQuantillonVault \
  --factory 0xStQEUROFactory \
  --yield-shift 0xYieldShift \
  --vault 1:AAVE1:0xMockAaveAdapter \
  --vault 2:MORPHO1:0xMorphoAdapter \
  --default-vault-id 2 \
  --enforce-source-bindings

See the dedicated runbook: docs/External-Vault-Onboarding-Runbook.md.

4. Seed the Version Manifest (one-time, per chain)

deployments/{chainId}/versions.json is the source of truth for what version is deployed. After upgrades it is maintained automatically by the UpgradeBase scripts, but it must be seeded once for contracts that were deployed before version() existed. This step reads each proxy's current implementation from its EIP-1967 slot on-chain.

Read-only — no private key required. It only issues eth_getStorageAt reads via cast; it sends no transactions and spends no gas. It needs only a Base RPC URL.

# chainId defaults to 8453 (Base mainnet). GIT_COMMIT tags the pre-versioning baseline.
RPC_URL="$BASE_RPC_URL" GIT_COMMIT=f1c55ad \
  ./scripts/deployment/backfill-versions.sh 8453

versions.json is committed (a .gitignore exception re-includes deployments/*/versions.json while the rest of deployments/ stays ignored), so deployed-version provenance syncs across workstations via git pull. Seed it once with the backfill above; thereafter the UpgradeBase scripts keep it current on each upgrade — commit the updated manifest so other machines pick it up.

After seeding, verify and inspect drift vs source:

make check-deployed-versions          # lists contracts whose deployed version != source version()
cast call <proxy> "version()(string)" --rpc-url "$BASE_RPC_URL"   # once a version()-bearing impl is live

Before the July 2026 implementation upgrades the manifest showed every contract as 0.0.0-unversioned (deployed) vs 1.0.0 (source) — i.e. "needs upgrade" — because no live implementation carried version() yet. Today every proxy except StorkOracle (parked) and TimeProvider (not a proxy) reports a live version(); each UpgradeBase run overwrites that contract's entry with the real deployed version + commit.


Accessing Deployed Addresses

deployments/{chainId}/addresses.json is a flat map keyed by PascalCase contract name (plus the external dependencies). On Base mainnet the key set is:

QuantillonVault, QEUROToken, QTIToken, UserPool, HedgerPool, FeeCollector, YieldShift,
stQEUROFactory, stQEUROToken (zero address: resolved per vault via stQEUROFactory),
OracleRouter, ChainlinkOracle, HyperliquidEurUsdOracle, LighterEurUsdOracle (inert), StorkOracle,
SlippageStorage, TimeProvider, Timelock, Multisig, USDC, EURUSD, USDCUSD

The file is a local deployment artifact (gitignored — only versions.json is tracked); the API Reference mirrors the mainnet values.

Programmatically (shell)

jq -r '.QEUROToken' deployments/8453/addresses.json
# "0x69aD4e6c49d6275D0e11b5515D98a89f029869AA"

Frontend format

update-frontend-addresses.sh writes the frontend addresses.json (FRONTEND_ADDRESSES_FILE) with the same PascalCase keys, nested per chain id:

{
  "8453": {
    "name": "Base",
    "isTestnet": false,
    "contracts": {
      "QuantillonVault": "0x...",
      "QEUROToken": "0x...",
      "QTIToken": "0x...",
      "UserPool": "0x...",
      "HedgerPool": "0x...",
      "FeeCollector": "0x...",
      "YieldShift": "0x...",
      "stQEUROFactory": "0x...",
      "stQEUROToken": "0x0000000000000000000000000000000000000000",
      "OracleRouter": "0x...",
      "ChainlinkOracle": "0x...",
      "HyperliquidEurUsdOracle": "0x...",
      "StorkOracle": "0x...",
      "TimeProvider": "0x...",
      "USDC": "0x..."
    }
  }
}

Contract Verification

Contracts are verified automatically when --verify is passed. For manual re-verification:

# Example: re-verify QEUROToken proxy on Base Sepolia
forge verify-contract \
  <PROXY_ADDRESS> \
  lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy \
  --chain-id 84532 \
  --etherscan-api-key $ETHERSCAN_API_KEY

Troubleshooting

Anvil not running

anvil --host 127.0.0.1 --port 8545 --accounts 10 --balance 10000

Missing environment file

cp .env.localhost .env
# or
cp .env.base-sepolia .env

Nonce desync on testnet

The deploy script polls for a stable nonce before broadcasting. If it keeps failing, try a different RPC URL (the default https://sepolia.base.org can occasionally lag). You can override by editing the NETWORKS map in deploy.sh.

Verification failed

Ensure ETHERSCAN_API_KEY is set and valid. If automatic verification fails, contracts can be re-verified using forge verify-contract after deployment.

USDC address is zero on localhost

Set USDC=<mock_address> in .env.localhost after deploying MockUSDC, or let deploy.sh handle it automatically with --with-mock-usdc.


Security Considerations

Private Key Management

  • Use a dedicated deployment wallet — never your main wallet
  • For production, use a hardware wallet or a cloud HSM
  • Rotate deployment keys after production deployment

Production Role Configuration

  • TREASURY, DEV_FUND, and COMMUNITY_FUND should be multisig wallets (e.g., Safe)
  • SINGLE_HEDGER should be an audited, authorized hedger address
  • After deployment, transfer core default-admin roles to the configured controller and operational governance/emergency roles to the multisig; verify the handover before enabling deposits

Never Commit Secrets

  • .env, .env.base, .env.base-sepolia and .env.localhost are tracked but git-crypt encrypted (.gitattributes): never commit them in plaintext and never disable the git-crypt filter
  • Use a secret manager (AWS Secrets Manager, HashiCorp Vault) for production CI/CD

Maintained by Quantillon Labs.

Reviewed release bindings and controller administration

build-upgrade-safe-txs.sh <implementation> <version> requires RPC_URL, RELEASE_MANIFEST and SAFE_TX_OUT_DIR. Both staging directories must be private (mode 0700), outside repositories and web roots. Never publish generated payloads. The manifest is a reviewed local JSON object containing chainId, sourceCommit (full Git SHA), safe, timelock, minimumDelay, contracts, and libraries. Each contract entry contains name, address (candidate), version, runtimeCodeHash, proxy, and currentImplementation. Each library entry contains name, fqn, address, version, and runtimeCodeHash. Derive expected hashes from the reproducible, reviewed build and verified library links; do not blindly bless whatever code an address currently returns.

For QuantillonVault 1.4.0 and later, its contract entry also requires a nonzero hedgerYieldRecipient equal to singleHedger() on the vault's configured HedgerPool. The builder validates that binding and the Safe's governance role. Its execute package contains an ordered, atomic Safe batch: configure the vault recipient to the hedger itself, then execute the scheduled controller upgrade. The schedule and cancel packages do not change the recipient. Revalidate the manifest immediately before execution; regenerate/review it if the hedger changes. The recipient setting does not automatically track subsequent hedger rotations.

The builder checks chain, runtime hashes, versions, UUPS identity, current implementation, controller, Safe permissions and the live delay. It creates a unique salt and matching schedule, execute and cancel payloads. Rehearse the exact payload on a pinned fork before proposing it. build-verifiable-impl.sh requires the same reviewed library bindings for every --lib; an address alone is insufficient. UpgradeBase and the vault upgrade script detect OZ controllers and direct operators to this Safe builder instead of the legacy proposal-registry interface.

The coordinated core activation grants the controller default-admin authority on all seven core proxies and every registered staking token, checks that authority through the scheduled batch, and renounces the Safe's default-admin role in the same atomic transaction. Preserve all operational roles and verify immediate Safe pause/resume plus delayed role grants/revocations in the rehearsal. The dapp reads current authority and produces matched schedule/execute actions when a controller is required. New staking series must complete the same admin handover before users can deposit; retain Safe governance/emergency roles separately.

After the confirmed activation, reconcile each proxy and linked library against the reviewed runtime hashes, read versions from live storage, and run the upgrade scripts' record action with the release commit, or the release manifest tool's record-live mode. The latter requires RELEASE_ACTIVATION_TX, plus executionSafeTxHash and operationId in the reviewed manifest; it checks the successful canonical Safe receipt, completed controller operation, and every live implementation/library binding before atomically updating versions.json. This is a required release-close step, not a candidate-deployment step. Update adapter inventory and all affected address/documentation entries only after their bindings change on chain. Re-run make check-deployed-versions and the dapp contract-drift check; verify production publisher, watchdog and rebalancer health before closing the release.

Storage gates recursively compare mappings, arrays and struct members and keep an append-only registry of assembly storage anchors and schemas. --update cannot approve an incompatible existing recursive layout. Run the gate's Python regression tests as well as Solidity tests. Static analysis includes every installed High/Medium detector and fails on unreviewed production results; stage reports privately.

Technical Upgrade: stQEURO Multi-Vault with stQEUROFactory

Historical technical record. This document describes the multi-vault refactor as designed at the time; the factory / vaultId model it introduces is the one live in production, but three things have changed since: the AaveVault contract referenced in sections 5-7 was retired — external yield flows through IExternalStakingVault adapters (see Architecture); stQEUROToken was rewritten as a standard ERC-4626 vault in v1.0.3, so the YIELD_MANAGER_ROLE grants and the distributeYield call described in sections 2, 4 and 11 no longer exist (yield reaches stakers through QuantillonVault.creditVaultYield, see Staking Yield Distribution); and on Base mainnet only vaultId = 2 (MORPHO1, MetaMorphoStakingVaultAdapter) is registered. Sections 2, 4, 5, 6 and 11 are kept as the historical design record.

Context

The protocol originally used a single stQEURO staking token for a single staking vault.
The architecture has been extended to support multiple vaults (identified by vaultId), with one dedicated token per vault:

  • vaultId = 1 -> stQEURO<VAULT_NAME_1>
  • vaultId = 2 -> stQEURO<VAULT_NAME_2>
  • ...

These tokens are not fungible with each other (distinct ERC20 addresses, distinct metadata, and distinct yield accounting).


Upgrade objective

  1. Replace the "single stQEURO token" model with an upgradeable factory.
  2. Keep stQEUROToken as the vault-level staking token implementation.
  3. Route yield (YieldShift) through vaultId.
  4. Enforce strict vault registration through an on-chain self-call.
  5. Update deployment flows, interfaces, and tests.

Updated components

1) New contract: stQEUROFactory

This contract introduces an orchestration layer to deploy and register one stQEURO token per vault dynamically.

Responsibilities

  • Deploy one ERC1967Proxy per vault pointing to the stQEUROToken implementation.
  • Keep resolution indexes vaultId <-> vault <-> token.
  • Store vault metadata (vaultName).
  • Provide resolution getters for YieldShift, scripts, and indexers.

Upgradeability and access control

  • Pattern: Initializable + AccessControlUpgradeable + SecureUpgradeable (UUPS via SecureUpgradeable).
  • Roles:
    • GOVERNANCE_ROLE: factory reconfiguration (implementation, yieldShift, treasury, etc.)
    • VAULT_FACTORY_ROLE: permission to register vaults

Main storage

  • stQEUROByVaultId[vaultId] -> token
  • stQEUROByVault[vault] -> token
  • vaultById[vaultId] -> vault
  • vaultIdByStQEURO[token] -> vaultId
  • _vaultNamesById[vaultId] -> vaultName
  • _vaultNameHashUsed[keccak256(vaultName)] -> bool

Strict registration: registerVault(uint256 vaultId, string vaultName)

Applied constraints:

  • onlyRole(VAULT_FACTORY_ROLE)
  • caller vault derived from msg.sender (no vault parameter): strict self-register
  • vaultId > 0
  • uniqueness:
    • vaultId not already used
    • vault not already registered
    • vaultName not already used
  • vaultName format:
    • length 1..12
    • allowed characters: A-Z, 0-9

Token creation:

  • Name: Staked Quantillon Euro {vaultName}
  • Symbol: stQEURO{vaultName}
  • Deploy an ERC1967Proxy pointing to the stQEUROToken implementation
  • Initialize the proxy with dynamic metadata (tokenName, tokenSymbol, vaultName)

Events

  • VaultRegistered(vaultId, vault, stQEUROToken, vaultName)
  • FactoryConfigUpdated(key, oldValue, newValue)

Governance reconfiguration

  • updateYieldShift(address)
  • updateTokenImplementation(address)
  • updateOracle(address)
  • updateTreasury(address)
  • updateTokenAdmin(address)

2) stQEUROToken evolution

stQEUROToken remains the vault-level token (stake/unstake/yield logic preserved), but can now be initialized with dynamic metadata.

Key changes

  • Added string public vaultName.
  • Added an overloaded initialize(...) supporting:
    • _tokenName
    • _tokenSymbol
    • _vaultName
  • Kept the legacy initializer (default metadata).
  • Centralized initialization in _initializeStQEURO(InitConfig memory cfg).

Roles

At initialization:

  • At initialization, DEFAULT_ADMIN_ROLE, GOVERNANCE_ROLE, EMERGENCY_ROLE -> admin. Before production activation, hand default-admin authority to the configured controller while preserving Safe governance/emergency roles; see the onboarding runbook.
  • YIELD_MANAGER_ROLE -> admin
  • YIELD_MANAGER_ROLE -> yieldShift (explicit grant)

3) QuantillonVault evolution (self-registration)

Additions:

  • stQEUROFactory (linked factory address)
  • stQEUROToken (token deployed for this vault)
  • stQEUROVaultId (registered vault id)
  • event StQEURORegistered(...)

New function:

  • selfRegisterStQEURO(address factory, uint256 vaultId, string vaultName)
    • onlyRole(GOVERNANCE_ROLE)
    • local anti double-registration (stQEUROToken == address(0))
    • factory call originates from the vault itself, enforcing msg.sender == vault on the factory side
    • persists local references for factory/token/vaultId

4) YieldShift evolution (multi-vault routing)

Dependency change

  • Old model: direct reference to a single stQEURO.
  • New model: reference to stQEUROFactory.

YieldDependencyConfig field replacement:

  • stQEURO -> stQEUROFactory

New signature

  • addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source)

Routing flow

  1. Verify global source authorization (authorizedYieldSources + sourceToYieldType).
  2. Pull USDC from source to YieldShift.
  3. Compute userAllocation / hedgerAllocation.
  4. Resolve target token through stQEUROFactory.getStQEUROByVaultId(vaultId).
  5. Revert if vault is not registered (address(0)).
  6. Keep coherent pull flow toward token:
    • safeIncreaseAllowance(stQEURO, userAllocation)
    • IstQEURO(stQEURO).distributeYield(userAllocation)

Source policy:

  • default remains global (no strict source -> vaultId binding).
  • optional strict mode is available through:
    • setSourceVaultBinding(source, vaultId)
    • clearSourceVaultBinding(source)
    • setSourceVaultBindingEnforcement(enabled)
  • when strict mode is enabled, addYield(vaultId, ...) reverts unless sourceToVaultId[msg.sender] == vaultId.

5) AaveVault evolution

Additions:

  • uint256 public yieldVaultId (governance config)
  • setYieldVaultId(uint256) (reverts if 0)
  • updateYieldShift(address) (explicit rewiring)

Change in harvestAaveYield():

  • validate yieldVaultId != 0
  • routing call:
    • yieldShift.addYield(yieldVaultId, netYield, bytes32("aave"))

6) Impacted interfaces

  • New: IStQEUROFactory
    • registerVault(vaultId, vaultName)
    • resolution getters (vaultId -> token, token -> vaultId, etc.)
  • IYieldShift
    • addYield becomes addYield(vaultId, yieldAmount, source)
    • dependency config: stQEUROFactory
    • optional strict source routing:
      • setSourceVaultBinding(source, vaultId)
      • clearSourceVaultBinding(source)
      • setSourceVaultBindingEnforcement(bool)
  • IAaveVault
    • setYieldVaultId(uint256)
    • updateYieldShift(address)
    • yieldVaultId()
  • IQuantillonVault
    • selfRegisterStQEURO(...)
    • getters stQEUROFactory, stQEUROToken, stQEUROVaultId
  • IstQEURO
    • overloaded initialize(...) with dynamic metadata

7) Deployment scripts and wiring

DeployQuantillon.s.sol is updated to:

  1. Deploy YieldShift.
  2. Deploy stQEUROToken implementation.
  3. Deploy stQEUROFactory (proxy) while injecting token implementation.
  4. Configure YieldShift with stQEUROFactory.
  5. Rewire AaveVault to YieldShift.
  6. Leave AaveVault.yieldVaultId unset until governance/core-team vault decision.
  7. Do not register any stQEURO vault token during bootstrap deployment.
  8. Register vaults later via explicit core-team governance flow.

At bootstrap, no vault-name environment variable is consumed by DeployQuantillon.s.sol.

Exports:

  • addresses and ABIs now include stQEUROFactory.

8) Breaking changes

Breaking changes assumed for this iteration:

  1. YieldShift.addYield(...) now requires vaultId.
  2. YieldShift dependency points to the factory instead of a single token.
  3. Deployment flows must explicitly register vaults.
  4. Integrations calling the old API addYield(yieldAmount, source) must be updated.

No on-chain legacy migration is included in this pass.


9) Validation and test coverage

New test

  • test/stQEUROFactory.t.sol
    • registration OK
    • multi-vault registration (2 active vaults)
    • duplicate vaultId
    • duplicate vault address
    • invalid/duplicate vaultName
    • unauthorized caller

Updated tests

  • YieldShift.t.sol (vaultId routing, factory dependency, strict source -> vaultId policy, multi-vault routing assertions)
  • AaveVault.t.sol (yieldVaultId, new addYield signature)
  • DeploymentSmoke.t.sol, IntegrationTests.t.sol, QuantillonInvariants.t.sol, LiquidationScenarios.t.sol, stQEUROToken.t.sol (initializer/signature alignment)

Result

  • forge build --skip test passes
  • targeted suites pass
  • forge test -q passes

10) Runbook: adding a new staking vault

To onboard vaultId = N:

  1. Deploy/configure the new vault (including governance roles).
  2. From governance, grant VAULT_FACTORY_ROLE to the vault address.
  3. Call vault.selfRegisterStQEURO(factory, N, VAULT_NAME).
  4. Verify:
    • factory.getStQEUROByVaultId(N) != 0
    • factory.getVaultById(N) == vault
    • factory.getVaultName(N) == VAULT_NAME
  5. If the vault receives yield through YieldShift, route addYield(N, ...) calls from the relevant source.
  6. Update address/ABI exports and the off-chain integration layer.

11) Attention points for next steps

Rotation runbook: updateTokenImplementation

Use this for future vault deployments only (already-deployed vault tokens are unchanged).

  1. Deploy the new stQEUROToken implementation contract.
  2. Smoke-test initialization compatibility off-chain:
    • verify the 9-argument initializer used by the factory still succeeds.
    • verify role wiring still grants YIELD_MANAGER_ROLE to YieldShift.
  3. From governance, execute:
    • stQEUROFactory.updateTokenImplementation(newImplementation).
  4. Register a canary vault and verify:
    • metadata (name, symbol, vaultName) is correct.
    • factory.getStQEUROByVaultId(canaryId) resolves as expected.
    • yield routing still works through YieldShift.addYield(canaryId, ...).
  5. If canary checks fail, roll back by re-pointing:
    • stQEUROFactory.updateTokenImplementation(previousImplementation).

Monitoring runbook: VaultRegistered and indexer consistency

Use scripts/deployment/monitor-stqeuro-factory.sh:

./scripts/deployment/monitor-stqeuro-factory.sh \
  --rpc-url <RPC_URL> \
  --factory <STQEURO_FACTORY_ADDRESS> \
  --from-block <START_BLOCK>

What it validates:

  1. Streams/parses VaultRegistered logs in the selected block range.
  2. For each event, checks on-chain registry consistency:
    • getStQEUROByVaultId(vaultId) == event.stQEUROToken
    • getVaultById(vaultId) == event.vault
    • getVaultIdByStQEURO(event.stQEUROToken) == vaultId
  3. Optionally compares against an indexer snapshot:
    • --indexer-snapshot <path-to-json>

Status of prior follow-ups

  1. Multi-vault integration tests: implemented.
  2. Optional strict source -> vaultId policy: implemented.
  3. updateTokenImplementation rotation procedure: documented.
  4. VaultRegistered + indexer consistency monitoring: implemented.

12) Executive summary

This upgrade introduces a robust factory layer that enables QEURO staking to scale across multiple vaults without mixing staking positions.

  • One vault = one dedicated stQEURO token.
  • Yield routing becomes explicitly keyed by vaultId.
  • Self-registration guarantees strict and auditable registration semantics.
  • Core deployment registers no vault; each vault is onboarded post-core with setup-external-vaults.sh (see the External Vault Onboarding Runbook). On Base mainnet only vaultId = 2 (MORPHO1) is registered.

Multi-Vault Staking Runtime Flow

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

This note describes the current vaultId-based runtime behavior for staking, minting, redemption, and hedger liquidity flows.

Core Runtime State

QuantillonVault tracks:

  • defaultStakingVaultId
  • stakingVaultAdapterById[vaultId]
  • stakingVaultActiveById[vaultId]
  • redemptionPriorityVaultIds[]
  • stQEUROTokenByVaultId[vaultId]
  • principalUsdcByVaultId[vaultId]
  • totalUsdcHeld
  • totalUsdcInExternalVaults

Mint and Stake Flows

The conversion selectors below are inner operations. In production signed mode, submit the permitted operation through executeWithQuote(bytes,bytes) with its exact authorization; bare unquoted conversion calls are rejected.

1) Mint (default routing)

  • mintQEURO(usdcAmount, minQeuroOut) calls internal mint flow with defaultStakingVaultId.
  • If default vault id is non-zero and valid, net USDC is auto-deployed to that vault adapter.
  • If default vault id is 0, net USDC remains in totalUsdcHeld.

2) Mint (explicit vault)

  • mintQEUROToVault(usdcAmount, minQeuroOut, vaultId) uses provided vaultId.

3) Mint + Stake (one-step)

  • mintAndStakeQEURO(usdcAmount, minQeuroOut, vaultId, minStQEUROOut):
    • Mints QEURO via the same vault-aware mint flow.
    • Resolves stQEUROTokenByVaultId[vaultId].
    • Stakes and transfers stQ token to caller.

Auto-deploy implementation

  • _mintQEUROCommit moves net amount from held balance to per-vault principal accounting when targetVaultId != 0.
  • _autoDeployToVault(vaultId, usdcAmount) deposits through configured adapter and emits UsdcDeployedToExternalVault.

Yield Distribution to Stakers

QuantillonVault 1.6.0 preserves the allocation introduced in 1.5.0 and allocates realized strategy yield by the harvest-time ratio of raw staked QEURO to total QEURO supply. Stakers receive their gross allocation after the configured haircut; treasury receives the unstaked allocation. The hedger receives only that haircut, with no base allocation for hedger collateral. There is no additional staking yield fee on vault credits; conversion costs and admission checks remain.

The release accepts one funded strategy and one outstanding staking series; registered empty strategies are allowed. It rejects unsupported simultaneous allocation. Raw staked QEURO includes unvested credit, while totalAssets() excludes yield not yet redeemable. Shareholders participate pro rata as yield vests; this does not make allocation time-weighted.

The keeper reads yieldDistributionConfig and the on-chain preview. hedgerBase remains zero for ABI compatibility. Older 1.4.x and legacy deployments retain their own models. See Yield Distribution 1.5.0.

Redemption Flow

redeemQEURO(qeuroAmount, minUsdcOut) (normal mode):

  • Computes required USDC and checks total collateral availability.
  • Uses _planExternalVaultWithdrawal(requiredUsdc) to compute deficit vs totalUsdcHeld.
  • Commit phase withdraws deficit through _withdrawUsdcFromExternalVaults when needed.

Withdrawal source order:

  • First: redemptionPriorityVaultIds (if configured).
  • Fallback: single-item array with defaultStakingVaultId.
  • If neither exists and held balance is insufficient, redemption reverts (InsufficientBalance).

Liquidation-mode redemption uses the same external-withdraw planning pattern.

Hedger Flow

Hedger opens / adds margin

  • HedgerPool transfers USDC into QuantillonVault.
  • vault.addHedgerDeposit(...) increases totalUsdcHeld.

Hedger closes / removes margin / liquidation payout

  • HedgerPool calls vault.withdrawHedgerDeposit(...).
  • Vault uses held USDC first; if needed, it withdraws from external vaults using the same priority logic as redemptions.

Governance and Operator Controls

QuantillonVault controls:

  • setStakingVault(vaultId, adapter, active) (GOVERNANCE_ROLE)
  • setDefaultStakingVaultId(vaultId) (GOVERNANCE_ROLE)
  • setRedemptionPriority(vaultIds[]) (GOVERNANCE_ROLE)
  • harvestAndDistributeVaultYield(vaultId) (YIELD_DISTRIBUTOR_ROLE) — harvest + 3-way split to stakers/hedger/treasury
  • creditVaultYield(vaultId, usdcAmount) (YIELD_DISTRIBUTOR_ROLE) — credit USDC into stQEURO as QEURO backing
  • setHedgerStakingYieldHaircutBps(bps) / setHedgerYieldRecipient(addr) (GOVERNANCE_ROLE)
  • deployUsdcToVault(vaultId, usdcAmount) (VAULT_OPERATOR_ROLE)

Factory binding:

  • selfRegisterStQEURO(factory, vaultId, vaultName) links vault id to stQ token (GOVERNANCE_ROLE).

Automatic vs Operational Actions

Automatic:

  • Mint routing to default/explicit vault (if configured).
  • Redemption and hedger withdrawals sourcing liquidity from external vaults when needed.

Operational:

  • Adapter configuration and activation.
  • Default vault and redemption-priority policy.
  • Deploying idle held USDC (deployUsdcToVault).
  • Harvesting + distributing adapter yield (harvestAndDistributeVaultYield).

Key Events for Indexer and Admin Read Models

  • VaultRegistered (factory)
  • StakingVaultConfigured
  • DefaultStakingVaultUpdated
  • RedemptionPriorityUpdated
  • UsdcDeployedToExternalVault
  • UsdcWithdrawnFromExternalVault
  • VaultYieldDistributed (harvest + 3-way split)

Practical Ops Notes

  • If vaultId config is missing/inactive, vault-aware actions revert (InvalidVault / config errors).
  • If held + external principal cannot satisfy required payouts, flows revert (InsufficientBalance).
  • Correct default and priority setup is critical to predictable redemption behavior.

Source Files

  • src/core/QuantillonVault.sol
  • src/core/HedgerPool.sol
  • src/core/stQEUROFactory.sol

Staking-ratio yield distribution — 1.5.0 release

This policy was introduced in vault 1.5.0 and is preserved by the signed-quote production release, vault 1.6.0, activated on 17 October 2026. Harvest conversion uses its bounded signed authorization. See Signed Quotes in Production.

The Base candidate contracts were deployed and source-verified on 29 September 2026. The production proxy was upgraded to 1.5.0 on 30 September 2026 at 09:21:13 UTC (11:21:13 Paris time), in Base block 51,985,363. QuantillonVault and its linked StakingYieldLibrary change from capital-weighted allocation to harvest-time staking-ratio allocation. The Morpho adapter and staking-token implementation do not change. The existing single-funded-strategy guard remains.

Economics

Let Y be actual harvested USDC, Q total QEURO supply, S the registered staking token's raw QEURO balance when it has outstanding shares (including credited, unvested yield), and h the haircut in basis points. Clamp S to Q. Snapshot S and Q before harvesting or minting.

  • Gross staker yield G = floor(Y × S / Q); G = 0 if Q is zero or no staking shares exist.
  • Hedger payout H = floor(G × h / 10,000).
  • Staker allocation = G − H; treasury allocation = Y − G.
  • Hedger collateral, unrealized P&L and reference exchange rates do not weight the allocation.
  • Zero haircut means no hedger payment, including the first harvest. Principal is never deducted.
  • Staking-ratio rounding remains with treasury; haircut rounding remains with stakers.

The strategy's harvested yield is assigned to QEURO backing under this policy. Before activation, review the actual funded strategy and the provenance of its principal; separately owned hedger strategy deposits or multiple funded strategies require explicit accounting outside this release.

This remains snapshot-weighted, not time-weighted: staking duration is not accumulated. The staker allocation is converted into QEURO and vests using the token's existing schedule, currently 24 hours. Existing conversion costs, oracle checks, execution admission, collateralization and mint eligibility remain enforced. The token's legacy yieldFee value is ignored for both harvested and directly credited yield. Direct creditVaultYield credits an already allocated amount and does not apply the harvest haircut again. Public mint/redeem fees are unchanged.

Compatibility

Storage layout and public selectors are unchanged. previewVaultYieldDistribution and VaultYieldBreakdown retain hedgerBase, now always zero. Preview estimates accrued yield; execution uses the adapter's actual liquid payout, so a liquidity limit may reduce all allocations. A successful allocation preview is not a guarantee that conversion admission will succeed. Conversion failure rolls back the entire harvest, USDC transfers and lastHarvest timestamp.

Deploy the version-aware dapp/backend/keeper release before activating the contract. It recognizes 1.4.x as capital and 1.5.x as staking-ratio, keeps older funding semantics, and disables the legacy staking-yield-fee control only for the new model (unknown versions cannot enable that control). The displayed provider APY remains an underlying historical rate, explicitly before deductions and conversion costs, not a guaranteed QEURO return. No new net-APY estimator is included.

Required release evidence

  1. Preserve unrelated local changes; build from the reviewed release commit and installed pinned dependencies. Run contract tests, keeper tests/typecheck, dapp typecheck and targeted UI/backend tests.

  2. Run ABI, storage-layout, size and version-bump gates. Bump versions for dependency-closure changes; do not overwrite the deployed-version manifest with candidate addresses.

  3. Rehearse the upgrade and zero/nonzero-haircut harvests on Base block 51,942,142 (deployed 1.4.0):

    REQUIRE_BASE_FORK=true FOUNDRY_PROFILE=production forge test \
      --match-contract StakingYieldUpgradeForkTest \
      --fork-url https://app.quantillon.money/api/rpc/base \
      --fork-block-number 51942142 -vv
    

    The tests upgrade only the local fork and check balances, private token vesting storage, configuration, timestamps, conservation, recipient balance deltas and subsequent vesting.

  4. Reconcile the live proxy version, EIP-1967 implementation and linked libraries against on-chain evidence. Record the current haircut, recipient, strategy binding and funding. The tracked version manifest may lag live state; do not infer the predecessor from that manifest alone.

  5. Run reproducible-bytecode checks for the library and vault. If the ordinary full-unit build differs from the verifier's pruned unit, use the existing build-verifiable-impl.sh workflow and rehearse the exact candidate runtime before deploying. Never deploy an unverified variant.

Activation

After release review, deploy the new library and the implementation linked to that exact library and the verified existing dependencies. Prepare the Safe schedule/execute operations using the live controller's delay and roles; the documented current delay is 12 hours. Keep transaction JSON and Safe payloads private, outside repositories and public hosting. The implementation is inert until the proxy upgrade executes. No initializer or storage migration is required.

Preserve the haircut (currently zero), hedger recipient, staking shares, existing vesting and keeper journal. Coordinate activation away from a keeper run in flight. The first harvest after activation uses the new policy for all pending yield, including yield accrued before activation. Historical payouts are not recomputed. Preserve the daily 03:00 UTC schedule.

After activation, verify version 1.5.0 and the exact implementation/library runtime hashes; update deployment provenance only from confirmed transactions. Invalidate/refresh version and fee snapshots. Confirm the preview has hedgerBase = 0 and haircut-only payout. Observe the first actual harvest: USDC allocations reconcile, the recipient receives no payout at zero haircut, QEURO is credited to stakers, syncVesting confirms, and the keeper reports a healthy served slot without duplicate harvests.

If these checks fail, stop further keeper attempts and investigate with the writer journal intact. Corrective upgrades follow governance; completed payouts cannot be rolled back automatically.

Base deployment and governance handoff — 29 September 2026

Source commit: d0232f8e3d5a072e18447345380d753ae91089cb.

ComponentCandidate addressDeployment block
StakingYieldLibrary 1.5.00x5dc57a0ba352E357afEbF9386fc3520CAD68605851,944,053
QuantillonVault 1.5.0 implementation0x4d1014C50Cb3AAfB5D45AECd5d47e05CFC5e529051,944,055

Both deployed runtimes match the independently reproduced build. The vault keeps the live ExecutionPricingLibrary, SecureUpgradeLibrary and TreasuryRecoveryLibrary bindings. The proxy address is unchanged: 0x833E5Ba510a241b21F1C60c987D1c49eB52E4a07.

The generated private schedule, execute and cancel package was rehearsed against Base block 51,944,104 using the actual Safe (two-owner threshold), controller and deployed candidates. The rehearsal proved early execution fails, cancellation works, the operation becomes ready only after 43,200 seconds, and the ordered recipient configuration plus upgrade succeeds through Safe MultiSend. Accounting, configuration, staking shares and vesting storage were preserved. At zero haircut, the post-upgrade preview paid no yield to the hedger.

Confirmed production activation — 30 September 2026

Safe transaction #78 completed the reviewed operation in Base transaction 0xc41087be…d3255b3. The Safe success event, completed controller operation, proxy implementation and all linked runtime hashes were verified. Accounting, QEURO supply, staking shares and token vesting storage were preserved across the activation block. The haircut remains zero and the preview pays no hedger yield. The dapp reports staking-ratio; the keeper remains healthy on its 03:00 UTC schedule.

The 30 September 03:00 UTC harvest occurred before activation and used the previous model. The first scheduled harvest under 1.5.0 is 1 October 2026 at 03:00 UTC (05:00 Paris time). Its actual allocation and vesting synchronization still need to be observed after that run. Deployment provenance is recorded in deployments/8453/versions.json; transaction payloads and execution evidence remain private.

Historical staking yield distribution — 1.4.0

Production uses 1.5.0 from 30 September 2026. See the current staking-ratio allocation and activation record. The capital-weighted model below is retained only as historical documentation.

Capital-based distribution (QuantillonVault 1.4.0)

This source describes the proposed 1.4.0 implementation. Deploying application changes alone does not activate it. Confirm version() on the target proxy; earlier versions retain the annual-funding model until upgraded.

Yield from the single funded external strategy belongs to three economic allocations:

  • Hedgers receive yield attributable to their effective collateral.
  • Stakers receive yield attributable to the backing of staked QEURO.
  • Treasury receives yield attributable to unstaked QEURO backing and existing protocol fees.

Governance may additionally redirect a percentage of gross earned staking yield to the configured hedger recipient. hedgerStakingYieldHaircutBps defaults to zero; 100 is 1%, 200 is 2%, and the maximum is 10,000 (100%). This is never an annual rate or a deduction from principal. The haircut applies before the existing staking yield fee.

Calculation

Immediately before harvesting, snapshot:

  • H: HedgerPool.getTotalEffectiveHedgerCollateral(price), including its existing P&L treatment.
  • U: QEURO total supply valued in USDC at a fresh validated EUR/USD reference price (supply * price / 1e30).
  • S: QEURO balance of the selected stQEURO token, capped at QEURO supply, or zero if there are no shareholders. This includes credited but unvested QEURO: vesting affects redemption, not economic ownership.
  • Q: QEURO total supply.
  • Y: USDC yield actually realized by the adapter, excluding tracked principal.
hedgerBase   = floor(Y * H / (H + U))
userPool     = Y - hedgerBase
stakerGross  = Q == 0 ? 0 : floor(userPool * S / Q)
treasuryBase = userPool - stakerGross
haircut      = floor(stakerGross * haircutBps / 10000)
hedgerShare  = hedgerBase + haircut
userShare    = stakerGross - haircut

If H + U == 0, orphaned yield goes to treasury. All amounts conserve realized yield; floor rounding remains in the residual allocations. A nonzero hedger payment requires a configured nonzero recipient: there is no implicit treasury fallback.

The snapshot uses economic ownership at harvest, including changes to balances or exchange rates before the transaction. It is not time-weighted participation accounting. Idle and deployed capital use the same pooled ownership weights; only strategy yield that is actually harvested is paid out.

Example

At 1 QEURO = 1 USDC, take 1,000 USDC of effective hedger collateral, 100 QEURO outstanding, 50 staked, and 110 USDC harvested:

HaircutHedgerStaker allocationTreasury base
0%100 USDC5 USDC5 USDC
1%100.05 USDC4.95 USDC5 USDC
2%100.10 USDC4.90 USDC5 USDC
100%105 USDC0 USDC5 USDC

Staker allocations above are before the existing staking fee and execution conversion into QEURO.

Credit, fees and vesting

harvestAndDistributeVaultYield(vaultId) remains role-gated, paused with the vault, and non-reentrant. The staker allocation goes through the existing _creditVaultYield path: staking yield fee, execution-pricing admission, collateralization validation and QEURO minting into stQEURO. The public mint fee is not additionally charged. Zero staker allocations skip crediting entirely.

There is no claim call. Credited QEURO vests under the token's existing schedule and increases redeemable value per share. Including unvested QEURO in the ownership snapshot does not make it immediately withdrawable. A failed admission, mint, transfer or oracle validation reverts the entire harvest, including its timestamp and transfers.

The initial release supports one funded strategy. Distribution rejects other deployed strategy principal, other registered strategies with underlying assets, or another registered series with outstanding shares. Registered empty series remain allowed. Factory registration must retain the existing factory so its registry remains complete. Multiple-strategy capital attribution requires a later extension.

Interfaces and compatibility

  • setHedgerStakingYieldHaircutBps(uint256): governance-only, accepts 0–10,000; emits HedgerStakingYieldHaircutUpdated.
  • hedgerStakingYieldHaircutBps(): public getter.
  • yieldDistributionConfig(vaultId): (haircutBps, hedgerRecipient, lastHarvest).
  • previewVaultYieldDistribution(vaultId): returns (realizedYield, hedgerBase, haircut, hedgerShare, userShare, treasuryShare) as a struct. Invoke using eth_call/simulateContract; the oracle's stateful interface means this is not a Solidity view. Shares calculation and validation with execution; realized yield and balances may change before mining.
  • VaultYieldDistributed: existing conserved aggregate event; userShare is after haircut but before existing staking fees.
  • VaultYieldBreakdown: supplemental event exposing hedger base and haircut separately.
  • harvestConfig: deprecated read; the first value is always zero after upgrade. Recipient and timestamp remain available.
  • setFundingRateAnnualBps: retained selector, explicitly reverts. The old storage slot stays in place and cannot initialize the new haircut.

Keepers continue to use lastHarvest for idempotency. There is no funding clock, time prorating, or first-harvest funding exemption. Clients identify contract semantics by version and do not relabel old funding data as a haircut.

Upgrade procedure

  1. Validate storage layout, ABI compatibility, semantic versions, runtime size and verification reproducibility. Deploy only the reviewed library/implementation artifacts through the normal authorized release process.
  2. Rehearse on a pinned Base fork through the protocol RPC API. Preserve balances, shares, vesting, execution configuration and harvest timestamps; prove a nonzero old funding rate becomes a zero new haircut.
  3. Stop recurring harvests. Settle accrued yield under the old implementation immediately before coordinated activation. If that cannot succeed, stop activation and resolve it rather than silently change the allocation of pending yield.
  4. Confirm one funded strategy. Resolve HedgerPool from the vault, read its nonzero singleHedger(), and use that account itself as hedgerYieldRecipient in the reviewed release manifest. The private Safe execute package sets that recipient through the Safe's governance role before executing the controller upgrade; execute those calls together as one atomic Safe batch. Revalidate the hedger immediately before execution; a hedger change invalidates the prepared recipient binding. Haircut starts at zero, but hedger capital yield still requires this recipient.
  5. Deploy compatible API, keeper and UI changes before resuming. Confirm configuration and the first distribution against the preview and events.
  6. Any later haircut change is a separate governance action.

Transaction proposals and review artifacts remain private. Never publish transaction JSON or Safe payloads in docs, public assets or releases.

Tests: StQEUROYieldDistribution.t.sol covers allocation, fees, vesting ownership, rollback and boundary cases; StakingYieldUpgradeFork.t.sol rehearses the UUPS upgrade and payment to singleHedger() in a local Base fork. Release rehearsals must set REQUIRE_BASE_FORK=true so an absent or incorrect fork fails instead of skipping. Use production compiler settings and an explicitly pinned block:

REQUIRE_BASE_FORK=true FOUNDRY_PROFILE=production forge test \
  --match-path test/StakingYieldUpgradeFork.t.sol \
  --fork-url "$RPC_URL" --fork-block-number "$FORK_BLOCK" -vv

Confirm the activated yieldDistributionConfig(vaultId) recipient equals HedgerPool.singleHedger() before resuming harvests. Repeat that configuration check when rotating the hedger; the recipient is an explicit governance setting and does not automatically follow a rotation.

External Vault Onboarding Runbook (setup-external-vaults.sh)

Why This Exists

Core deployment (DeployQuantillon) intentionally does not bootstrap external adapters. After core deploy:

  • defaultStakingVaultId = 0
  • redemption priority is empty
  • no adapter is registered via setStakingVault

Use this runbook to onboard staking vault adapters post-deploy.

Script

./scripts/deployment/setup-external-vaults.sh

The script performs, for each --vault entry:

  1. Grant VAULT_FACTORY_ROLE to QuantillonVault on stQEUROFactory.
  2. Register the vault token via selfRegisterStQEURO(factory, vaultId, vaultName).
  3. Configure adapter binding via setStakingVault(vaultId, adapter, true).
  4. Grant VAULT_MANAGER_ROLE to QuantillonVault on the adapter (adapter.grantRole(VAULT_MANAGER_ROLE, vault)).

Adapter yield is distributed via QuantillonVault.harvestAndDistributeVaultYield — grant YIELD_DISTRIBUTOR_ROLE to the yield keeper separately (yield distribution no longer routes through YieldShift).

Required — do not skip. The vault calls adapter.depositUnderlying / withdrawUnderlying / harvestYieldToVault, all gated by VAULT_MANAGER_ROLE on the adapter. The adapter constructor grants that role only to its admin, so without step 4 every external-vault deploy / redeem-sourcing / harvest reverts. Step 4's signer must hold the adapter's DEFAULT_ADMIN_ROLE.

Recommended — seed each new stQEURO series. To avoid the well-known first-depositor donation/rounding edge case, the operator should make the first stake into each newly registered stQEURO vault (a small deposit) so it is never bootstrapped by an arbitrary first external user.

Then it sets:

  • setDefaultStakingVaultId(...)
  • setRedemptionPriority(...)

Prerequisites

  • Foundry installed (cast available in PATH)
  • Core deployment completed (QuantillonVault, stQEUROFactory, and optionally YieldShift addresses)
  • Deployer/admin key with required governance/role permissions
  • RPC URL for target chain

Parameters

  • --rpc-url <url>: chain RPC endpoint
  • --private-key <hex>: signer private key
  • --quantillon-vault <address>: deployed QuantillonVault
  • --factory <address>: deployed stQEUROFactory
  • --vault <vaultId:vaultName:adapterAddress>: repeatable vault definition
    • vaultId: positive integer
    • vaultName: uppercase/digits token label (factory validation applies)
    • adapterAddress: external strategy adapter for that vault id
  • --default-vault-id <vaultId>: optional, defaults to first --vault item

Ready-To-Run Examples

The AAVE1 entries below are localhost / testnet examples over mock adapters. On Base mainnet only vaultId = 2 (MORPHO1, MetaMorphoStakingVaultAdapter) is registered; there is no Aave vault in production.

Localhost (31337)

./scripts/deployment/setup-external-vaults.sh \
  --rpc-url http://localhost:8545 \
  --private-key "$PRIVATE_KEY" \
  --quantillon-vault 0xQuantillonVault \
  --factory 0xStQEUROFactory \
  --vault 1:AAVE1:0xMockAaveAdapter \
  --vault 2:MORPHO1:0xMorphoAdapter \
  --default-vault-id 2

Base Sepolia (84532)

./scripts/deployment/setup-external-vaults.sh \
  --rpc-url https://sepolia.base.org \
  --private-key "$PRIVATE_KEY" \
  --quantillon-vault 0xQuantillonVault \
  --factory 0xStQEUROFactory \
  --vault 1:AAVE1:0xAdapterA \
  --vault 2:MORPHO1:0xAdapterB

Verification Commands

Export addresses once:

export RPC_URL=http://localhost:8545
export QUANTILLON_VAULT=0xQuantillonVault
export FACTORY=0xStQEUROFactory
export YIELD_SHIFT=0xYieldShift

Check default vault:

cast call "$QUANTILLON_VAULT" "defaultStakingVaultId()(uint256)" --rpc-url "$RPC_URL"

Check per-vault token + adapter exposure:

cast call "$FACTORY" "getStQEUROByVaultId(uint256)(address)" 1 --rpc-url "$RPC_URL"
cast call "$QUANTILLON_VAULT" "getVaultExposure(uint256)(address,bool,uint256,uint256)" 1 --rpc-url "$RPC_URL"

Check routing events:

cast logs --rpc-url "$RPC_URL" --address "$QUANTILLON_VAULT" "StakingVaultConfigured(uint256,address,bool)"
cast logs --rpc-url "$RPC_URL" --address "$QUANTILLON_VAULT" "DefaultStakingVaultUpdated(uint256,uint256)"
cast logs --rpc-url "$RPC_URL" --address "$QUANTILLON_VAULT" "RedemptionPriorityUpdated(uint256[])"

If --yield-shift was used, verify source authorization/binding:

cast call "$YIELD_SHIFT" "authorizedYieldSources(address)(bool)" 0xAdapterA --rpc-url "$RPC_URL"
cast call "$YIELD_SHIFT" "sourceToVaultId(address)(uint256)" 0xAdapterA --rpc-url "$RPC_URL"
cast call "$YIELD_SHIFT" "enforceSourceVaultBinding()(bool)" --rpc-url "$RPC_URL"

Routing configuration coverage

Starting with QuantillonVault 1.5.1, the effective redemption set must include all tracked external principal. A nonempty priority list is the effective set; an empty list selects only the default vault. Both setRedemptionPriority and setDefaultStakingVaultId reject a resulting set whose included principal differs from totalUsdcInExternalVaults.

When changing the default while the old default remains funded, first configure an explicit priority list containing every funded vault. Then change the default. Retain the old vault in the priority list until its tracked principal is withdrawn or its loss is recognized. Zero reported NAV alone does not allow removal. A complete explicit list can also restore coverage to an existing configuration.

stQEURO reserve activation

stQEUROToken 1.3.0 uses matched virtual reserves while retaining 18-decimal shares and the existing ERC-4626 interface. New and empty series start at parity. A populated series calibrates its reserve ceiling to its current share price at the first accounting synchronization; that ceiling remains fixed until the series empties. The effective reserve is capped by backing after losses so withdrawals cannot quote more than the real assets. Vesting and the deposit round-trip loss bound remain in force.

For an existing proxy, rehearse the upgrade against a recent pinned block and verify its share precision, balances, supply, metadata, and withdrawal quotes. While the series is unpaused, execute upgradeToAndCall(newImplementation, abi.encodeCall(syncVesting, ())) through the authorized controller so reserve activation is atomic with the upgrade. For paused maintenance, use one authorized Safe batch to pause, execute the controller's scheduled upgrade, call syncVesting from the Safe holding GOVERNANCE_ROLE, and unpause. A paused token rejects a sync from a controller without that role. Verify all roles during rehearsal and recheck the live state before execution.

Calibration preserves the existing exchange rate; it does not reset a series with an already extreme asset-to-share ratio. If ordinary deposit previews are zero or fail the round-trip loss bound before activation, stop that series' rollout and resolve its migration without changing existing holders' claims. Update the factory's token implementation separately for future series; that setting does not upgrade existing token proxies.

Adapter withdrawal and migration invariants

An adapter must report the actual USDC withdrawn. A one-unit ERC-4626 rounding shortfall is permitted only when the aggregate flow can still satisfy the payout; principal trackers follow the actual return. Changing the ERC-4626 endpoint inside a current adapter requires zero old shares. Replacing an adapter must be rehearsed atomically while the vault is paused.

Replacing a funded MetaMorpho adapter

MetaMorphoAdapterMigration is a one-use, Safe-called helper bound at construction to one vault id and one old/new adapter pair using the same USDC and MetaMorpho vault. It reads the current principal at execution, withdraws it, collects the remaining yield, deposits the principal into the replacement, and leaves yield as uncredited USDC at the replacement. It changes neither QEURO supply nor the vault's tracked principal. Redeposition may lose at most one USDC base unit to ERC-4626 rounding, and replacement backing must still cover all principal.

In one Safe transaction: pause the vault, grant the helper temporary manager roles on both adapters and governance on the vault, grant the vault manager access to the replacement, call migrate(), revoke all temporary roles, retire the vault's manager role on the old adapter, and remove the Safe's direct manager role on the replacement. Verify the configured adapter and preserved accounting before resuming operations. Failure anywhere reverts the entire transaction.

The retired legacy adapter must have zero principal and zero valued underlying. Its withdrawal-only interface can leave fractional ERC-4626 shares worth zero USDC base units; retain its address in the deployment history and record that residue explicitly. The migration rejects losses, unavailable liquidity and principal mismatches, and cannot be reused or directed to another destination.

New-series authority check

After creating a staking series, preserve the governance and emergency roles assigned to the Safe, grant DEFAULT_ADMIN_ROLE to the configured controller, verify its controller configuration, and renounce the Safe's default-admin role. Complete creation, role handover and registry activation in one reviewed Safe batch while deposits are paused. The factory's initial tokenAdmin is a bootstrap identity; changing it to the controller alone would also redirect governance and emergency roles, so it is not a substitute for this explicit handover. Verify all role holders before unpausing and include the new series in subsequent upgrade inventories.

Dapp compatibility

Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.

Contract releases are accepted only after the frontend contract-drift check and dapp tests pass.

  1. Build Solidity artifacts and run scripts/deployment/copy-abis.sh against a private dapp checkout.
  2. Run npm run check:contract-drift, npm run test:run, and npm run build in quantillon-dapp.
  3. Read minCollateralizationRatioForMinting from the deployed vault at runtime; source defaults and UI fallbacks are not authoritative.
  4. Treat a reverted harvestAndDistributeVaultYield as retryable. The transaction is atomic and adapter yield remains available.
  5. Verify generated ABI selectors for changed oracle, pricing, vault, and stQEURO contracts before deployment.

Normal conversions must use the signed wrapper on the authorized Vault or UserPool target. Complete token approval before requesting an executable quote. Validate chain, wallet, module, target, exact inner calldata, amounts and expiry; require user review again if output changes. Bare legacy mint/redeem calls are rejected in signed mode.

Test approval followed by issuance, 45-second expiry, replay rejection, wallet/chain changes, capacity exhaustion, stale reference, pause, and ambiguous transaction recovery. Simulate the exact wrapper call. Dashboard and keeper valuation must obtain a fresh signed reference in read-only simulation rather than equating an idle cache with unavailable delivery. A failed harvest remains atomic. The current emergency budget is zero; no automatic reference-only fallback should be offered.

Admin compatibility is part of release acceptance. Simulate each generated action from the Safe against current state. If the target's admin is the configured controller, simulate from the controller and generate matching schedule and execute transactions using its live minimum delay and a unique salt. Ordinary Safe actions remain direct. Do not turn a failed business-logic check into an unchecked proposal. Test both pre-handover and post-handover authority, rejected calls, role grants, and the retained immediate pause/resume controls. Keep generated transaction files local; they are never public application assets.

Contents

IMigrationAdapter

Git Source

Functions

USDC

function USDC() external view returns (address);

metaMorphoVault

function metaMorphoVault() external view returns (address);

principalDeposited

function principalDeposited() external view returns (uint256);

totalUnderlying

function totalUnderlying() external view returns (uint256);

withdrawUnderlying

function withdrawUnderlying(uint256 amount) external returns (uint256);

harvestYieldToVault

function harvestYieldToVault() external returns (uint256);

depositUnderlying

function depositUnderlying(uint256 amount) external returns (uint256);

IMigrationVault

Git Source

Functions

paused

function paused() external view returns (bool);

usdc

function usdc() external view returns (address);

getVaultExposure

function getVaultExposure(uint256 id) external view returns (address, bool, uint256, uint256);

setStakingVault

function setStakingVault(uint256 id, address adapter, bool active) external;

MetaMorphoAdapterMigration

Git Source

Inherits: IVersioned, ReentrancyGuard

Title: MetaMorphoAdapterMigration

Moves one configured adapter's principal and uncredited yield atomically.

Grant temporary manager roles on both adapters and governance on the paused vault, then revoke them in the same Safe transaction. No user tokens are minted or burned.

Constants

safe

address public immutable safe

vault

IMigrationVault public immutable vault

oldAdapter

IMigrationAdapter public immutable oldAdapter

newAdapter

IMigrationAdapter public immutable newAdapter

usdc

IERC20 public immutable usdc

vaultId

uint256 public immutable vaultId

State Variables

completed

bool public completed

Functions

constructor

Binds this one-use operation to a Safe, vault and adapter pair.

constructor(address safe_, address vault_, uint256 id_, address old_, address next_) ;

version

Identifies the immutable migration implementation.

function version() external pure override returns (string memory);

migrate

Migrates current balances without embedding an amount that can become stale.

Leaves yield uncredited as idle USDC at the replacement adapter. A legacy adapter can retain fractional shares worth zero USDC base units; no valued assets may remain. Any failure rolls back the withdrawals, deposits, registry change and completion flag.

function migrate() external nonReentrant;

Events

Migrated

event Migrated(
    uint256 indexed vaultId,
    address indexed oldAdapter,
    address indexed newAdapter,
    uint256 principal,
    uint256 uncreditedYield
);

Errors

Unauthorized

error Unauthorized();

InvalidConfiguration

error InvalidConfiguration();

InvalidState

error InvalidState();

BalanceMismatch

error BalanceMismatch();

IRebalancerSafe

Git Source

Functions

execTransactionFromModuleReturnData

function execTransactionFromModuleReturnData(address to, uint256 value, bytes calldata data, uint8 operation)
    external
    returns (bool success, bytes memory returnData);

QuantillonRebalancerModule

Git Source

Inherits: ReentrancyGuard

Title: QuantillonRebalancerModule

A Safe-owned, non-upgradeable permission to add/remove margin on one position.

No arbitrary execution, transfers, delegatecalls, position entry/exit or bridging. The operator pays gas; USDC always moves between the Safe and HedgerPool's vault. Install only after independent review. Policy changes require a call from the Safe.

Note: security-contact: team@quantillon.money

Constants

safe

address public immutable safe

hedgerPool

IHedgerPool public immutable hedgerPool

usdc

IERC20 public immutable usdc

vault

IQuantillonVault public immutable vault

positionId

uint256 public immutable positionId

State Variables

operator

address public operator

paused

bool public paused = true

limits

Limits public limits

nonce

uint256 public nonce

lastExecution

uint256 public lastExecution

usageDay

uint256 public usageDay

currentDayUsage

uint256 public currentDayUsage

previousDayUsage

uint256 public previousDayUsage

Functions

constructor

constructor(address safe_, address pool_, uint256 positionId_, address operator_, Limits memory limits_) ;

version

Reports this standalone module's release version.

function version() external pure returns (string memory);

configure

Changes the operator and policy; existing usage and cooldown are preserved.

function configure(address operator_, Limits calldata limits_) external nonReentrant;

setPaused

Lets the Safe pause or resume automation without blocking its owner transactions.

function setPaused(bool paused_) external nonReentrant;

addMargin

Adds margin using an exact, atomic Safe approval and preserves its reserve.

Deposits remain possible with an invalid oracle to allow collateral recovery.

function addMargin(uint256 amount, uint256 expectedNonce, uint256 deadline) external nonReentrant;

removeMargin

Removes margin to the Safe, then checks fresh position and protocol solvency atomically.

function removeMargin(uint256 amount, uint256 expectedNonce, uint256 deadline) external nonReentrant;

windowUsage

Conservative rolling-day usage: sum of the current and previous UTC day.

This bounds every rolling 24h period, but can retain usage for almost 48h.

function windowUsage() public view returns (uint256);

_configure

function _configure(address operator_, Limits memory limits_) private;

_authorize

function _authorize(uint256 amount, uint256 expectedNonce, uint256 deadline) private;

_checkWithdrawalFloors

function _checkWithdrawalFloors() private;

_approve

function _approve(uint256 amount) private;

_execute

function _execute(address target, bytes memory data) private returns (bytes memory result);

Events

Configured

event Configured(address indexed operator, Limits limits);

PauseChanged

event PauseChanged(bool paused);

MarginRebalanced

event MarginRebalanced(uint256 indexed nonce, uint256 indexed positionId, bool increase, uint256 amount);

Errors

Unauthorized

error Unauthorized();

InvalidConfiguration

error InvalidConfiguration();

ModulePaused

error ModulePaused();

InvalidRequest

error InvalidRequest();

WrongPositionOwner

error WrongPositionOwner();

DependenciesChanged

error DependenciesChanged();

LimitExceeded

error LimitExceeded();

CooldownActive

error CooldownActive();

InvalidOracle

error InvalidOracle();

PositionFloorBreached

error PositionFloorBreached();

VaultFloorBreached

error VaultFloorBreached();

SafeReserveBreached

error SafeReserveBreached();

SafeExecutionFailed

error SafeExecutionFailed();

TokenOperationFailed

error TokenOperationFailed();

UnexpectedBalanceChange

error UnexpectedBalanceChange();

Structs

Limits

struct Limits {
    uint256 maxActionUsdc;
    uint256 maxWindowUsdc;
    uint256 cooldownSeconds;
    uint256 minSafeReserveUsdc;
    uint256 minMarginBps;
    uint256 marginBufferBps;
    uint256 vaultCrBufferBps;
}

Contents

Contents

IMockAaveVault

Git Source

Functions

depositUnderlying

Deposits underlying assets into the mock Aave vault.

Forwards parameters to the underlying vault and relies on the adapter-level access control and nonReentrant protection in the main adapter.

Notes:

  • security: External dependency call; trust model is environment-specific.

  • validation: Reverts on invalid amount or vault-side checks.

  • state-changes: Updates vault share/asset accounting.

  • events: Vault implementation may emit deposit events.

  • errors: Reverts on vault-side failures.

  • reentrancy: Interface declaration only.

  • access: Access control defined by vault implementation.

  • oracle: No oracle dependencies.

function depositUnderlying(uint256 assets, address onBehalfOf) external returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of USDC to deposit.
onBehalfOfaddressAccount credited with vault shares.

Returns

NameTypeDescription
sharesuint256Vault shares minted for the deposit.

withdrawUnderlying

Withdraws underlying assets from the mock Aave vault.

Forwards parameters to the underlying vault. Reverts and/or returns values are handled by the calling adapter.

Notes:

  • security: External dependency call; trust model is environment-specific.

  • validation: Reverts on insufficient balance or vault-side checks.

  • state-changes: Updates vault share/asset accounting.

  • events: Vault implementation may emit withdrawal events.

  • errors: Reverts on vault-side failures.

  • reentrancy: Interface declaration only.

  • access: Access control defined by vault implementation.

  • oracle: No oracle dependencies.

function withdrawUnderlying(uint256 assets, address to) external returns (uint256 withdrawn);

Parameters

NameTypeDescription
assetsuint256Amount of USDC requested.
toaddressRecipient of withdrawn USDC.

Returns

NameTypeDescription
withdrawnuint256Actual USDC withdrawn.

totalUnderlyingOf

Returns underlying assets held for an account.

View helper used by the adapter to compute available yield.

Notes:

  • security: Read-only helper.

  • validation: No input validation required at interface level.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if implementation cannot service read.

  • reentrancy: Not applicable for view function.

  • access: Public view at implementation level.

  • oracle: No oracle dependencies.

function totalUnderlyingOf(address account) external view returns (uint256);

Parameters

NameTypeDescription
accountaddressAccount to query.

Returns

NameTypeDescription
<none>uint256Underlying USDC-equivalent amount for account.

AaveStakingVaultAdapter

Git Source

Inherits: AccessControl, ReentrancyGuard, IExternalStakingVault

Title: AaveStakingVaultAdapter

Generic external vault adapter for Aave-like third-party vaults.

Mirrors MorphoStakingVaultAdapter structure for symmetric localhost testing. Wraps a MockAaveVault (simple share-accounting mock) and routes yield to YieldShift.

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_MANAGER_ROLE

bytes32 public constant VAULT_MANAGER_ROLE = keccak256("VAULT_MANAGER_ROLE")

USDC

IERC20 public immutable USDC

State Variables

aaveVault

IMockAaveVault public aaveVault

principalDeposited

uint256 public principalDeposited

Functions

constructor

Initializes Aave adapter dependencies and roles.

Grants DEFAULT_ADMIN_ROLE, GOVERNANCE_ROLE, and VAULT_MANAGER_ROLE, then stores dependency pointers used by the adapter functions.

Notes:

  • security: Validates non-zero dependency addresses.

  • validation: Reverts on zero address.

  • state-changes: Initializes role assignments and adapter dependency pointers.

  • events: No events emitted by constructor.

  • errors: Reverts with ZeroAddress on invalid inputs.

  • reentrancy: Not applicable - constructor only.

  • access: Public constructor.

  • oracle: No oracle dependencies.

constructor(address admin, address usdc_, address aaveVault_) ;

Parameters

NameTypeDescription
adminaddressAdmin address granted governance and manager roles.
usdc_addressUSDC token address.
aaveVault_addressMock Aave vault address.

depositUnderlying

Deposits USDC into the configured Aave vault.

Tracks principal and forwards the deposit to aaveVault.depositUnderlying.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount or zero-share deposit outcome.

  • state-changes: Increases principalDeposited and updates vault position.

  • events: Emits downstream transfer/deposit events from dependencies.

  • errors: Reverts on transfer/approval/deposit failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function depositUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 sharesReceived);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).

Returns

NameTypeDescription
sharesReceiveduint256Aave vault shares received for the deposit.

withdrawUnderlying

Withdraws USDC principal from the configured Aave vault.

Withdraws up to the tracked principal, then transfers the withdrawn USDC to msg.sender.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount or when no principal is tracked.

  • state-changes: Decreases principalDeposited and updates vault position.

  • events: Emits downstream transfer/withdrawal events from dependencies.

  • errors: Reverts on withdrawal mismatch or transfer failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function withdrawUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
usdcAmountuint256Requested USDC withdrawal amount (6 decimals).

Returns

NameTypeDescription
usdcWithdrawnuint256Actual USDC withdrawn and transferred to caller.

harvestYieldToVault

Harvests accrued yield from the Aave vault and transfers it as USDC to the caller (the vault).

Withdraws only the amount above tracked principal, then transfers it to msg.sender (the vault) so the caller can apply its own distribution policy.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Returns zero when no yield is available; reverts only on downstream failures.

  • state-changes: Leaves principalDeposited unchanged; transfers realized USDC to the caller.

  • events: Emits downstream transfer events from dependencies.

  • errors: Reverts on downstream withdrawal or transfer failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function harvestYieldToVault()
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 realizedYield);

Returns

NameTypeDescription
realizedYielduint256USDC yield harvested and transferred to the caller (6 decimals).

totalUnderlying

Returns current underlying balance controlled by this adapter.

Reads the underlying amount from the configured aaveVault.

Notes:

  • security: Read-only helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if downstream vault read fails.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function totalUnderlying() external view override returns (uint256 underlyingBalance);

Returns

NameTypeDescription
underlyingBalanceuint256Underlying USDC-equivalent balance in the Aave vault.

setAaveVault

Updates the configured Aave vault endpoint.

Updates the aaveVault pointer; the adapter uses the new vault for future deposits/withdrawals.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on zero address input.

  • state-changes: Updates aaveVault pointer.

  • events: Emits AaveVaultUpdated.

  • errors: Reverts with ZeroAddress for invalid input.

  • reentrancy: No external calls after state change.

  • access: Restricted to governance role.

  • oracle: No oracle dependencies.

function setAaveVault(address newAaveVault) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newAaveVaultaddressNew Aave vault address.

Events

AaveVaultUpdated

event AaveVaultUpdated(address indexed oldVault, address indexed newVault);

MetaMorphoStakingVaultAdapter

Git Source

Inherits: AccessControl, ReentrancyGuard, IExternalStakingVault, IVersioned

Title: MetaMorphoStakingVaultAdapter

Adapter for MetaMorpho ERC-4626 vaults such as 0xBEEFE94c8aD530842bfE7d8B397938fFc1cb83b2.

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_MANAGER_ROLE

bytes32 public constant VAULT_MANAGER_ROLE = keccak256("VAULT_MANAGER_ROLE")

USDC

IERC20 public immutable USDC

State Variables

metaMorphoVault

IERC4626 public metaMorphoVault

principalDeposited

uint256 public principalDeposited

Functions

version

Semantic version of this non-upgradeable adapter.

Version changes accompany adapter behavior changes.

Notes:

  • security: Read-only metadata.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Public.

  • oracle: None.

function version() external pure override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string.

constructor

Initializes MetaMorpho adapter dependencies and roles.

Configures governance/manager roles, immutable USDC reference, and validates that the MetaMorpho ERC-4626 vault's asset matches USDC.

Notes:

  • security: Validates non-zero dependencies and matching ERC-4626 asset.

  • validation: Reverts on zero address or asset mismatch.

  • state-changes: Initializes role assignments and adapter dependency pointers.

  • events: No events emitted by constructor.

  • errors: Reverts with ZeroAddress or InvalidAddress.

  • reentrancy: Not applicable - constructor only.

  • access: Public constructor.

  • oracle: No oracle dependencies.

constructor(address admin, address usdc_, address metaMorphoVault_) ;

Parameters

NameTypeDescription
adminaddressAdmin address granted default-admin, governance, and manager roles.
usdc_addressUSDC token address.
metaMorphoVault_addressMetaMorpho ERC-4626 vault address (asset must equal usdc_).

depositUnderlying

Deposits USDC into the MetaMorpho ERC-4626 vault and tracks principal.

Pulls USDC from caller, deposits into the ERC-4626 vault using a scoped approval, and increases tracked principal by the deposited amount.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount, insufficient deposit capacity, or zero-share outcome.

  • state-changes: Increases principalDeposited and updates the ERC-4626 vault position.

  • events: Emits downstream transfer/deposit events from dependencies.

  • errors: Reverts with InvalidAmount or InsufficientBalance on failed checks.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function depositUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 sharesReceived);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).

Returns

NameTypeDescription
sharesReceiveduint256MetaMorpho shares minted to this adapter.

withdrawUnderlying

Withdraws tracked principal from MetaMorpho and returns USDC to the caller.

Caps the withdrawal to tracked principal, redeems from the ERC-4626 vault, verifies the received amount, decreases tracked principal, then transfers USDC to the caller.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount, no tracked principal, insufficient liquidity, or shortfall.

  • state-changes: Decreases principalDeposited and updates the ERC-4626 vault position.

  • events: Emits downstream transfer/withdrawal events from dependencies.

  • errors: Reverts with InvalidAmount or InsufficientBalance on failed checks.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function withdrawUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
usdcAmountuint256Requested USDC amount (6 decimals).

Returns

NameTypeDescription
usdcWithdrawnuint256Actual USDC amount withdrawn and transferred to the caller.

harvestYieldToVault

Harvests accrued ERC-4626 share yield and transfers it as USDC to the caller (the vault).

Transfers the realized USDC to msg.sender (the vault) so the caller can apply its own distribution policy. Caps to the vault's liquid withdrawable amount and leaves tracked principal unchanged.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Returns zero when no yield is available; reverts only on downstream failures.

  • state-changes: Leaves principalDeposited unchanged; transfers realized USDC to the caller.

  • events: Emits downstream transfer events from dependencies.

  • errors: Reverts with InvalidAmount on withdrawal mismatch or downstream failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function harvestYieldToVault()
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 realizedYield);

Returns

NameTypeDescription
realizedYielduint256USDC yield harvested and transferred to the caller (6 decimals).

writeDownPrincipal

Writes down tracked principal to the current ERC-4626 underlying value.

This records an externally observed loss so future withdrawals cannot rely on unavailable principal. It never transfers funds or changes share ownership.

Notes:

  • security: Governance-only loss recognition.

  • validation: Requires current underlying to be below tracked principal.

  • state-changes: Decreases principalDeposited.

  • events: PrincipalWrittenDown.

  • errors: InvalidCondition when no loss is present.

  • reentrancy: Protected by nonReentrant.

  • access: GOVERNANCE_ROLE.

  • oracle: No oracle dependency.

function writeDownPrincipal() external onlyRole(GOVERNANCE_ROLE) nonReentrant returns (uint256 writtenDown);

Returns

NameTypeDescription
writtenDownuint256Amount removed from tracked principal.

totalUnderlying

Returns the USDC value of MetaMorpho shares plus idle USDC.

Read helper used by QuantillonVault for exposure accounting; delegates to _totalUnderlying.

Notes:

  • security: Read-only helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if the downstream ERC-4626 read fails.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function totalUnderlying() external view override returns (uint256 underlyingBalance);

Returns

NameTypeDescription
underlyingBalanceuint256Underlying USDC-equivalent balance held via ERC-4626 shares.

setMetaMorphoVault

Updates the configured MetaMorpho ERC-4626 vault endpoint.

Governance maintenance hook; validates the new vault's asset matches USDC before swapping.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on zero address or asset mismatch with USDC.

  • state-changes: Updates metaMorphoVault pointer.

  • events: Emits MetaMorphoVaultUpdated.

  • errors: Reverts with ZeroAddress or InvalidAddress for invalid input.

  • reentrancy: No external calls after state change.

  • access: Restricted to governance role.

  • oracle: No oracle dependencies.

function setMetaMorphoVault(address newMetaMorphoVault) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newMetaMorphoVaultaddressNew MetaMorpho ERC-4626 vault address.

_totalUnderlying

Returns the USDC-equivalent value of this adapter's MetaMorpho shares.

Converts the adapter's ERC-4626 shares and adds idle USDC, including any rounding buffer.

Notes:

  • security: Internal read-only helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if the downstream ERC-4626 read fails.

  • reentrancy: Not applicable for view function.

  • access: Internal.

  • oracle: No oracle dependencies.

function _totalUnderlying() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256Underlying USDC-equivalent amount held via ERC-4626 shares.

Events

PrincipalWrittenDown

event PrincipalWrittenDown(uint256 previousPrincipal, uint256 currentPrincipal);

MetaMorphoVaultUpdated

event MetaMorphoVaultUpdated(address indexed oldVault, address indexed newVault);

IMockMorphoVault

Git Source

Functions

depositUnderlying

Deposits underlying assets into the mock Morpho vault.

Test-only vault interface used by the adapter in localhost simulations.

Notes:

  • security: External dependency call; trust model is environment-specific.

  • validation: Reverts on invalid amount or vault-side checks.

  • state-changes: Updates vault share/asset accounting.

  • events: Vault implementation may emit deposit events.

  • errors: Reverts on vault-side failures.

  • reentrancy: Interface declaration only.

  • access: Access control defined by vault implementation.

  • oracle: No oracle dependencies.

function depositUnderlying(uint256 assets, address onBehalfOf) external returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of USDC to deposit.
onBehalfOfaddressAccount credited with vault shares.

Returns

NameTypeDescription
sharesuint256Vault shares minted for the deposit.

withdrawUnderlying

Withdraws underlying assets from the mock Morpho vault.

Test-only vault interface used by the adapter in localhost simulations.

Notes:

  • security: External dependency call; trust model is environment-specific.

  • validation: Reverts on insufficient balance or vault-side checks.

  • state-changes: Updates vault share/asset accounting.

  • events: Vault implementation may emit withdrawal events.

  • errors: Reverts on vault-side failures.

  • reentrancy: Interface declaration only.

  • access: Access control defined by vault implementation.

  • oracle: No oracle dependencies.

function withdrawUnderlying(uint256 assets, address to) external returns (uint256 withdrawn);

Parameters

NameTypeDescription
assetsuint256Amount of USDC requested.
toaddressRecipient of withdrawn USDC.

Returns

NameTypeDescription
withdrawnuint256Actual USDC withdrawn.

totalUnderlyingOf

Returns underlying assets held for an account.

Read helper used by the adapter for principal/yield accounting.

Notes:

  • security: Read-only helper.

  • validation: No input validation required at interface level.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if implementation cannot service read.

  • reentrancy: Not applicable for view function.

  • access: Public view at implementation level.

  • oracle: No oracle dependencies.

function totalUnderlyingOf(address account) external view returns (uint256);

Parameters

NameTypeDescription
accountaddressAccount to query.

Returns

NameTypeDescription
<none>uint256Underlying USDC-equivalent amount for account.

MorphoStakingVaultAdapter

Git Source

Inherits: AccessControl, ReentrancyGuard, IExternalStakingVault

Title: MorphoStakingVaultAdapter

Generic external vault adapter for Morpho-like third-party vaults.

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_MANAGER_ROLE

bytes32 public constant VAULT_MANAGER_ROLE = keccak256("VAULT_MANAGER_ROLE")

USDC

IERC20 public immutable USDC

State Variables

morphoVault

IMockMorphoVault public morphoVault

principalDeposited

uint256 public principalDeposited

Functions

constructor

Initializes Morpho adapter dependencies and roles.

Configures governance/operator roles and immutable USDC reference.

Notes:

  • security: Validates non-zero dependency addresses.

  • validation: Reverts on zero address.

  • state-changes: Initializes role assignments and adapter dependency pointers.

  • events: No events emitted by constructor.

  • errors: Reverts with ZeroAddress on invalid inputs.

  • reentrancy: Not applicable - constructor only.

  • access: Public constructor.

  • oracle: No oracle dependencies.

constructor(address admin, address usdc_, address morphoVault_) ;

Parameters

NameTypeDescription
adminaddressAdmin address granted governance and manager roles.
usdc_addressUSDC token address.
morphoVault_addressMock Morpho vault address.

depositUnderlying

Deposits USDC into the configured Morpho vault.

Pulls USDC from caller, deposits to Morpho, and increases tracked principal.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount or zero-share deposit outcome.

  • state-changes: Increases principalDeposited and updates vault position.

  • events: Emits downstream transfer/deposit events from dependencies.

  • errors: Reverts on transfer/approval/deposit failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function depositUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 sharesReceived);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).

Returns

NameTypeDescription
sharesReceiveduint256Morpho vault shares received for the deposit.

withdrawUnderlying

Withdraws USDC principal from the configured Morpho vault.

Caps withdrawal to tracked principal, redeems from Morpho, then returns USDC to caller.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount or when no principal is tracked.

  • state-changes: Decreases principalDeposited and updates vault position.

  • events: Emits downstream transfer/withdrawal events from dependencies.

  • errors: Reverts on withdrawal mismatch or transfer failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function withdrawUnderlying(uint256 usdcAmount)
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
usdcAmountuint256Requested USDC withdrawal amount (6 decimals).

Returns

NameTypeDescription
usdcWithdrawnuint256Actual USDC withdrawn and transferred to caller.

harvestYieldToVault

Harvests accrued yield from Morpho and transfers it as USDC to the caller (the vault).

Withdraws only the amount above tracked principal, then transfers it to msg.sender (the vault) so the caller can apply its own distribution policy.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Returns zero when no yield is available; reverts only on downstream failures.

  • state-changes: Leaves principalDeposited unchanged; transfers realized USDC to the caller.

  • events: Emits downstream transfer events from dependencies.

  • errors: Reverts on downstream withdrawal or transfer failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function harvestYieldToVault()
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 realizedYield);

Returns

NameTypeDescription
realizedYielduint256USDC yield harvested and transferred to the caller (6 decimals).

totalUnderlying

Returns current underlying balance controlled by this adapter.

Read helper used by QuantillonVault for exposure accounting.

Notes:

  • security: Read-only helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: May revert if downstream vault read fails.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function totalUnderlying() external view override returns (uint256 underlyingBalance);

Returns

NameTypeDescription
underlyingBalanceuint256Underlying USDC-equivalent balance in Morpho.

setMorphoVault

Updates the configured Morpho vault endpoint.

Governance maintenance hook for swapping vault implementation/address.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on zero address input.

  • state-changes: Updates morphoVault pointer.

  • events: Emits MorphoVaultUpdated.

  • errors: Reverts with ZeroAddress for invalid input.

  • reentrancy: No external calls after state change.

  • access: Restricted to governance role.

  • oracle: No oracle dependencies.

function setMorphoVault(address newMorphoVault) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newMorphoVaultaddressNew Morpho vault address.

Events

MorphoVaultUpdated

event MorphoVaultUpdated(address indexed oldVault, address indexed newVault);

Contents

YieldShift

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IVersioned

Title: YieldShift

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Dynamic yield distribution system balancing rewards between users and hedgers

Main characteristics:

  • Dynamic yield allocation based on pool balance ratios
  • Time-weighted average price (TWAP) calculations for stability
  • Multiple yield sources integration (Aave, fees, interest differentials)
  • Automatic yield distribution with holding period requirements
  • Emergency pause mechanism for crisis situations
  • Upgradeable via UUPS pattern

Yield shift mechanics:

  • Base yield shift determines default allocation (default 50/50)
  • Maximum yield shift caps allocation changes (default 90/10)
  • Adjustment speed controls how quickly shifts occur
  • Target pool ratio defines optimal balance point
  • Real-time calculations based on pool metrics

Distribution algorithm:

  • Monitors user pool vs hedger pool size ratios
  • Adjusts yield allocation to incentivize balance
  • Higher user pool → more yield to hedgers (attract hedging)
  • Higher hedger pool → more yield to users (attract deposits)
  • Gradual adjustments prevent dramatic shifts
  • Flash deposit protection through eligible pool size calculations
  • Only deposits meeting holding period requirements count toward yield distribution

Yield sources:

  • Aave yield from USDC deposits in lending protocols
  • Protocol fees from minting, redemption, and trading
  • Interest rate differentials from hedging operations
  • External yield farming opportunities
  • Authorized source validation for security

Time-weighted calculations:

  • 24-hour TWAP for pool size measurements
  • Historical data tracking for trend analysis
  • Maximum history length prevents unbounded storage
  • Drift tolerance for timestamp validation
  • Automatic data cleanup and optimization

Holding period requirements:

  • Minimum 7-day holding period for yield claims
  • Prevents yield farming attacks and speculation
  • Encourages long-term protocol participation
  • Tracked per user with deposit timestamps
  • Enhanced protection against flash deposit manipulation
  • Eligible pool sizes exclude recent deposits from yield calculations
  • Dynamic discount system based on deposit timing and activity

Security features:

  • Role-based access control for all critical operations
  • Reentrancy protection for all external calls
  • Emergency pause mechanism for crisis situations
  • Upgradeable architecture for future improvements
  • Authorized yield source validation
  • Secure yield distribution mechanisms
  • Flash deposit attack prevention through holding period requirements
  • Eligible pool size calculations for yield distribution
  • Time-weighted protection against yield manipulation

Integration points:

  • User pool for deposit and staking metrics
  • Hedger pool for hedging exposure metrics
  • Aave vault for yield generation and harvesting
  • stQEURO token for user yield distribution
  • USDC for yield payments and transfers

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

YIELD_MANAGER_ROLE

bytes32 public constant YIELD_MANAGER_ROLE = keccak256("YIELD_MANAGER_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

MIN_HOLDING_PERIOD

uint256 public constant MIN_HOLDING_PERIOD = 7 days

TWAP_PERIOD

uint256 public constant TWAP_PERIOD = 24 hours

MAX_TIME_ELAPSED

uint256 public constant MAX_TIME_ELAPSED = 365 days

MIN_UPDATE_INTERVAL

Minimum interval between permissionless distribution recalculations.

uint256 public constant MIN_UPDATE_INTERVAL = 1 hours

MAX_HISTORY_LENGTH

uint256 public constant MAX_HISTORY_LENGTH = 1000

State Variables

usdc

IERC20 public usdc

userPool

IUserPool public userPool

hedgerPool

IHedgerPool public hedgerPool

mockAaveVault

Note: deprecated: Vestigial state: mockAaveVault is never read or called by YieldShift logic (user yield accrues via creditVaultYield -> stQEURO). Retained only to preserve the live proxy's storage layout and ABI; do not wire or rely on it.

IMockAaveVault private mockAaveVault

stQEUROFactory

IStQEUROFactory public stQEUROFactory

baseYieldShift

uint256 public baseYieldShift

maxYieldShift

uint256 public maxYieldShift

adjustmentSpeed

uint256 public adjustmentSpeed

targetPoolRatio

uint256 public targetPoolRatio

currentYieldShift

uint256 public currentYieldShift

lastUpdateTime

uint256 public lastUpdateTime

totalYieldGenerated

uint256 public totalYieldGenerated

totalYieldDistributed

uint256 public totalYieldDistributed

userYieldPool

uint256 public userYieldPool

hedgerYieldPool

uint256 public hedgerYieldPool

treasury

address public treasury

yieldSources

mapping(bytes32 => uint256) public yieldSources

yieldSourceNames

bytes32[] public yieldSourceNames

authorizedYieldSources

mapping(address => bool) public authorizedYieldSources

sourceToYieldType

mapping(address => bytes32) public sourceToYieldType

userPendingYield

mapping(address => uint256) public userPendingYield

hedgerPendingYield

mapping(address => uint256) public hedgerPendingYield

userLastClaim

mapping(address => uint256) public userLastClaim

hedgerLastClaim

mapping(address => uint256) public hedgerLastClaim

lastDepositTime

mapping(address => uint256) public lastDepositTime

userPoolHistory

PoolSnapshot[] public userPoolHistory

hedgerPoolHistory

PoolSnapshot[] public hedgerPoolHistory

yieldShiftHistory

YieldShiftSnapshot[] public yieldShiftHistory

sourceToVaultId

mapping(address => uint256) public sourceToVaultId

enforceSourceVaultBinding

bool public enforceSourceVaultBinding

poolHistoryCount

Monotonic count of pool snapshots recorded.

Drives the O(1) ring-buffer write position for userPoolHistory/hedgerPoolHistory (both written in lockstep). Appended at the end of storage (append-only).

uint256 public poolHistoryCount

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructor for YieldShift implementation

Sets up the time provider and disables initialization on implementation for security

Notes:

  • security: Validates time provider address and disables initialization on implementation

  • validation: Validates time provider is not zero address

  • state-changes: Sets time provider and disables initializers

  • events: No events emitted

  • errors: Throws ZeroAddress if time provider is zero

  • reentrancy: Not protected - constructor only

  • access: Public constructor

  • oracle: No oracle dependencies

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the time provider contract

initialize

Initialize the YieldShift contract

Sets up the contract with all required addresses and roles

Notes:

  • security: Validates all addresses are not zero

  • validation: Validates all input addresses

  • state-changes: Initializes ReentrancyGuard, AccessControl, and Pausable

  • events: Emits initialization events

  • errors: Throws if any address is zero

  • reentrancy: Protected by initializer modifier

  • access: Public initializer

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address _usdc,
    address _userPool,
    address _hedgerPool,
    address _mockAaveVault,
    address _stQEUROFactory,
    address _timelock,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress of the admin role
_usdcaddressAddress of the USDC token contract
_userPooladdressAddress of the user pool contract
_hedgerPooladdressAddress of the hedger pool contract
_mockAaveVaultaddressAddress of the Aave vault contract
_stQEUROFactoryaddressAddress of the stQEURO factory contract
_timelockaddressAddress of the timelock contract
_treasuryaddressAddress of the treasury

bootstrapDefaults

Governance bootstrap to set initial histories and source metadata after minimal init

Lazily initializes historical arrays and default authorized yield sources

Notes:

  • security: Restricted to governance; reads trusted state only

  • validation: Relies on prior initialization guarantees

  • state-changes: Records initial snapshots and default yield source metadata

  • events: Emits none (pure bookkeeping)

  • errors: Reverts if caller lacks governance role

  • reentrancy: Not applicable

  • access: Governance-only

  • oracle: Not applicable

function bootstrapDefaults() external;

updateYieldDistribution

Updates the yield distribution between users and hedgers

Recalculates and applies new yield distribution ratios based on current pool states

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateYieldDistribution() external nonReentrant whenNotPaused;

_updateYieldDistribution

Recalculates distribution from current aggregate pool sizes.

Called after the public cadence gate or governance force-update guard.

Notes:

  • security: Does not assert per-holder stake-age eligibility.

  • validation: Pool integrations must return valid metrics.

  • state-changes: Updates shift, timestamp, and history.

  • events: YieldDistributionUpdated.

  • errors: Propagates pool integration failures.

  • reentrancy: Caller holds nonReentrant.

  • access: Internal.

  • oracle: None.

function _updateYieldDistribution() internal;

addYield

Add yield from authorized sources

Adds yield from authorized sources and distributes it according to current yield shift

Notes:

  • security: Validates caller is authorized for the yield source

  • validation: Validates yield amount is positive and matches actual received

  • state-changes: Updates yield sources and total yield generated

  • events: Emits YieldAdded event

  • errors: Throws if caller is unauthorized or yield amount mismatch

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to authorized yield sources

  • oracle: No oracle dependencies

function addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source) external nonReentrant;

Parameters

NameTypeDescription
vaultIduint256Registered vault identifier used to resolve the target stQEURO token
yieldAmountuint256Amount of yield to add (6 decimals)
sourcebytes32Source identifier for the yield

claimHedgerYield

Claim hedger yield

Claims yield for a hedger

Notes:

  • security: Validates caller is authorized

  • validation: Validates hedger has pending yield

  • state-changes: Updates hedger pending yield and transfers USDC

  • events: Emits HedgerYieldClaimed event

  • errors: Throws if caller is unauthorized or insufficient yield

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to hedger or hedger pool

  • oracle: No oracle dependencies

function claimHedgerYield(address hedger) external nonReentrant returns (uint256 yieldAmount);

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger to claim yield for

Returns

NameTypeDescription
yieldAmountuint256Amount of yield claimed

_calculateOptimalYieldShift

Calculate optimal yield shift based on current pool ratio

Calculates optimal yield allocation to incentivize pool balance

Notes:

  • security: Uses tolerance checks to prevent excessive adjustments

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _calculateOptimalYieldShift(uint256 poolRatio) internal view returns (uint256);

Parameters

NameTypeDescription
poolRatiouint256Current ratio between user and hedger pools (basis points)

Returns

NameTypeDescription
<none>uint256Optimal yield shift percentage (basis points)

_applyGradualAdjustment

Apply gradual adjustment to yield shift to prevent sudden changes

Gradually adjusts yield shift based on adjustmentSpeed to prevent volatility

Notes:

  • security: Limits adjustment speed to prevent sudden changes

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _applyGradualAdjustment(uint256 targetShift) internal view returns (uint256);

Parameters

NameTypeDescription
targetShiftuint256Target yield shift percentage (basis points)

Returns

NameTypeDescription
<none>uint256Adjusted yield shift percentage (basis points)

_getCurrentPoolMetrics

Get current pool metrics

Returns current pool sizes and ratio for yield shift calculations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _getCurrentPoolMetrics()
    internal
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio);

Returns

NameTypeDescription
userPoolSizeuint256Current user pool size
hedgerPoolSizeuint256Current hedger pool size
poolRatiouint256Ratio of user to hedger pool sizes

_getEligiblePoolMetrics

Get current aggregate pool metrics used for allocation

Allocation uses aggregate balances and does not claim per-holder stake-age filtering

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _getEligiblePoolMetrics()
    internal
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio);

Returns

NameTypeDescription
userPoolSizeuint256Current aggregate user pool size
hedgerPoolSizeuint256Current aggregate hedger pool size
poolRatiouint256Ratio of eligible pool sizes

_isWithinTolerance

Check if a value is within tolerance of a target value

Helper function for yield shift calculations

Notes:

  • security: Uses safe arithmetic to prevent overflow

  • validation: No input validation required - pure function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _isWithinTolerance(uint256 value, uint256 target, uint256 toleranceBps) internal pure returns (bool);

Parameters

NameTypeDescription
valueuint256The value to check
targetuint256The target value
toleranceBpsuint256Tolerance in basis points (e.g., 1000 = 10%)

Returns

NameTypeDescription
<none>boolTrue if value is within tolerance, false otherwise

updateLastDepositTime

Updates the last deposit timestamp for a user

Called by UserPool to track user deposit timing for yield calculations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateLastDepositTime(address user) external;

Parameters

NameTypeDescription
useraddressThe user address to update

getYieldDistributionBreakdown

Returns detailed breakdown of yield distribution

Shows how yield is allocated between different pools and stakeholders

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getYieldDistributionBreakdown()
    external
    view
    returns (uint256 userYieldPool_, uint256 hedgerYieldPool_, uint256 distributionRatio);

Returns

NameTypeDescription
userYieldPool_uint256Yield allocated to user pool
hedgerYieldPool_uint256Yield allocated to hedger pool
distributionRatiouint256Current distribution ratio between pools

getPoolMetrics

Returns comprehensive metrics for both user and hedger pools

Provides detailed analytics about pool performance and utilization

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPoolMetrics()
    external
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio, uint256 targetRatio);

Returns

NameTypeDescription
userPoolSizeuint256Total size of user pool
hedgerPoolSizeuint256Total size of hedger pool
poolRatiouint256Current ratio between pools
targetRatiouint256Target ratio between pools

calculateOptimalYieldShift

Calculates the optimal yield shift based on current market conditions

Uses algorithms to determine best yield distribution strategy

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function calculateOptimalYieldShift() external view returns (uint256 optimalShift, uint256 currentDeviation);

Returns

NameTypeDescription
optimalShiftuint256Recommended yield shift percentage
currentDeviationuint256Current deviation from optimal shift

getYieldSources

Returns information about all yield sources

Provides details about different yield-generating mechanisms

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getYieldSources()
    external
    view
    returns (uint256 aaveYield, uint256 protocolFees, uint256 interestDifferential, uint256 otherSources);

Returns

NameTypeDescription
aaveYielduint256Yield from Aave protocol
protocolFeesuint256Protocol fees collected
interestDifferentialuint256Interest rate differential yield
otherSourcesuint256Other miscellaneous yield sources

getHistoricalYieldShift

Returns a lightweight historical yield-shift summary for a period

Uses the latest in-period snapshot (or current shift) to avoid O(n) scans.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getHistoricalYieldShift(uint256 period)
    external
    view
    returns (uint256 averageShift, uint256 maxShift, uint256 minShift, uint256 volatility);

Parameters

NameTypeDescription
perioduint256The time period to analyze (in seconds)

Returns

NameTypeDescription
averageShiftuint256Representative shift for the period
maxShiftuint256Same as averageShift in compact summary mode
minShiftuint256Same as averageShift in compact summary mode
volatilityuint256Always 0 in compact summary mode

getYieldPerformanceMetrics

Returns compact performance metrics for yield operations

Uses aggregate pools directly to avoid cross-contract reads.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getYieldPerformanceMetrics()
    external
    view
    returns (
        uint256 totalYieldDistributed_,
        uint256 averageUserYield,
        uint256 averageHedgerYield,
        uint256 yieldEfficiency
    );

Returns

NameTypeDescription
totalYieldDistributed_uint256Total yield distributed to date
averageUserYielduint256Aggregate user yield pool
averageHedgerYielduint256Aggregate hedger yield pool
yieldEfficiencyuint256Distributed / generated ratio (bps)

_calculateUserAllocation

Calculate user allocation from current yield shift

Calculates how much yield should be allocated to users

Notes:

  • security: Uses safe arithmetic to prevent overflow

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _calculateUserAllocation() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256User allocation amount based on current yield shift percentage

_calculateHedgerAllocation

Calculate hedger allocation from current yield shift

Calculates how much yield should be allocated to hedgers

Notes:

  • security: Uses safe arithmetic to prevent overflow

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _calculateHedgerAllocation() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256Hedger allocation amount based on current yield shift percentage

configureYieldModel

Batch-updates all yield model parameters.

Applies a new configuration for baseYieldShift, maxYieldShift, adjustmentSpeed and targetPoolRatio in a single governance transaction. Uses YieldValidationLibrary to enforce sane bounds and invariants.

Notes:

  • security: Only governance may call; validates that maxYieldShift >= baseYieldShift and that all parameters stay within library-defined limits.

  • validation: Reverts if yield shifts, adjustment speed or target ratio are out of bounds.

  • state-changes: Updates baseYieldShift, maxYieldShift, adjustmentSpeed, targetPoolRatio.

  • events: None – consumers should read the updated state via view functions.

  • errors: InvalidShiftRange if maxYieldShift < baseYieldShift; library errors otherwise.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to governance via AccessControlLibrary.onlyGovernance.

  • oracle: No direct oracle access – operates purely on configuration values.

function configureYieldModel(YieldModelConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgYieldModelConfigStruct containing the new yield model configuration: - baseYieldShift: baseline user share (bps) when pools are balanced. - maxYieldShift: maximum deviation from baseline (bps). - adjustmentSpeed: how fast the shift moves toward the optimal value. - targetPoolRatio: desired user/hedger pool ratio (bps).

configureDependencies

Batch-updates external dependency addresses used for yield distribution.

Wires or re-wires the userPool, hedgerPool, mockAaveVault, stQEUROFactory and treasury references in a single governance transaction.

Notes:

  • security: Only governance may call; validates required addresses and allows optional mockAaveVault.

  • validation: Uses AccessControlLibrary / YieldValidationLibrary to check addresses.

  • state-changes: Updates userPool, hedgerPool, mockAaveVault, stQEUROFactory, treasury.

  • events: None – downstream contracts emit their own events on meaningful actions.

  • errors: Library validation errors on zero/invalid addresses.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to governance via AccessControlLibrary.onlyGovernance.

  • oracle: No direct oracle access – configuration only.

function configureDependencies(YieldDependencyConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgYieldDependencyConfigStruct containing the new dependency configuration: - userPool: UserPool contract address. - hedgerPool: HedgerPool contract address. - mockAaveVault: MockAaveVault contract address. - stQEUROFactory: stQEURO factory contract address. - treasury: treasury address receiving recovered funds.

setYieldSourceAuthorization

Sets authorization status and yield type for a yield source.

Governance function mapping a source address to a logical yield type (e.g. "aave", "fees") and toggling whether that source is allowed to push yield via addYield.

Notes:

  • security: Only governance may call; prevents untrusted contracts from minting yield.

  • validation: Reverts on zero source address; clears mapping when authorized is false.

  • state-changes: Updates authorizedYieldSources[source] and sourceToYieldType[source].

  • events: None – yield events are emitted when yield is actually added.

  • errors: Library validation errors for invalid addresses.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to governance via AccessControlLibrary.onlyGovernance.

  • oracle: No oracle dependencies.

function setYieldSourceAuthorization(address source, bytes32 yieldType, bool authorized) external;

Parameters

NameTypeDescription
sourceaddressAddress of the yield source whose authorization is being updated.
yieldTypebytes32Logical yield category identifier (e.g., keccak256("aave")).
authorizedboolTrue to authorize the source, false to revoke authorization.

setSourceVaultBinding

Binds a yield source to a single vault id for optional strict routing.

When strict mode is enabled, calls from source can only route yield to vaultId.

Notes:

  • security: Governance-only control over source/vault routing boundaries.

  • validation: Reverts on zero source address or zero vault id.

  • state-changes: Updates sourceToVaultId[source].

  • events: Emits SourceVaultBindingUpdated.

  • errors: ZeroAddress / InvalidVault on invalid inputs.

  • reentrancy: Not applicable.

  • access: Restricted to governance.

  • oracle: No oracle dependencies.

function setSourceVaultBinding(address source, uint256 vaultId) external;

Parameters

NameTypeDescription
sourceaddressYield source address to bind.
vaultIduint256Vault id that this source is allowed to target.

clearSourceVaultBinding

Clears the vault binding for a yield source.

In strict mode, a cleared source must be rebound before it can call addYield.

Notes:

  • security: Governance-only.

  • validation: Reverts on zero source address.

  • state-changes: Resets sourceToVaultId[source] to zero.

  • events: Emits SourceVaultBindingUpdated with vault id 0.

  • errors: ZeroAddress on invalid input.

  • reentrancy: Not applicable.

  • access: Restricted to governance.

  • oracle: No oracle dependencies.

function clearSourceVaultBinding(address source) external;

Parameters

NameTypeDescription
sourceaddressYield source address to unbind.

setSourceVaultBindingEnforcement

Enables or disables strict source-to-vault enforcement.

When enabled, addYield requires sourceToVaultId[msg.sender] == vaultId.

Notes:

  • security: Governance-only mode toggle.

  • validation: No extra validation required.

  • state-changes: Updates enforceSourceVaultBinding.

  • events: Emits SourceVaultBindingModeUpdated.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Restricted to governance.

  • oracle: No oracle dependencies.

function setSourceVaultBindingEnforcement(bool enabled) external;

Parameters

NameTypeDescription
enabledboolTrue to enforce source/vault binding, false for permissive routing.

updateYieldAllocation

Updates yield allocation for a specific user or hedger

Called by pools to update individual yield allocations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateYieldAllocation(address user, uint256 amount, bool isUser) external;

Parameters

NameTypeDescription
useraddressThe user or hedger address
amountuint256The allocation amount
isUserboolTrue if user, false if hedger

emergencyYieldDistribution

Executes emergency yield distribution with specified amounts

Emergency function to manually distribute yield during critical situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyYieldDistribution(uint256 userAmount, uint256 hedgerAmount) external;

Parameters

NameTypeDescription
userAmountuint256Amount to distribute to user pool
hedgerAmountuint256Amount to distribute to hedger pool

pauseYieldDistribution

Pauses all yield distribution operations

Emergency function to halt yield distribution during critical situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pauseYieldDistribution() external;

resumeYieldDistribution

Resumes yield distribution operations after being paused

Restarts yield distribution when emergency is resolved

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function resumeYieldDistribution() external;

isYieldSourceAuthorized

Check if a yield source is authorized

Checks if a yield source is authorized for a specific yield type

Checks if a yield source is authorized for a specific yield type

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isYieldSourceAuthorized(address source, bytes32 yieldType) external view returns (bool);

Parameters

NameTypeDescription
sourceaddressSource address
yieldTypebytes32Yield type identifier

Returns

NameTypeDescription
<none>boolTrue if authorized

checkAndUpdateYieldDistribution

Checks current conditions and updates yield distribution if needed

Automated function to maintain optimal yield distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function checkAndUpdateYieldDistribution() external;

forceUpdateYieldDistribution

Forces an immediate update of yield distribution

Emergency function to bypass normal update conditions and force distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function forceUpdateYieldDistribution() external nonReentrant whenNotPaused;

getTimeWeightedAverage

Get time weighted average of pool history

Calculates time weighted average of pool history over a specified period

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getTimeWeightedAverage(PoolSnapshot[] storage poolHistory, uint256 period, bool isUserPool)
    internal
    view
    returns (uint256);

Parameters

NameTypeDescription
poolHistoryPoolSnapshot[]Array of pool snapshots
perioduint256Time period for calculation
isUserPoolboolWhether this is for user pool or hedger pool

Returns

NameTypeDescription
<none>uint256uint256 Time weighted average value

_recordPoolSnapshot

Record pool snapshot

Records current pool metrics as a snapshot for historical tracking

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _recordPoolSnapshot() internal;

_recordSnapshotPair

Writes one snapshot to both pool histories in lockstep.

Both arrays share poolHistoryCount, so the ring write position is computed once.

Notes:

  • security: Bounded O(1) write; no external calls

  • validation: None - values are pre-computed by the caller

  • state-changes: Appends/overwrites both pool histories and increments poolHistoryCount

  • events: None

  • errors: None

  • reentrancy: Not protected - internal, no external calls

  • access: Internal

  • oracle: No oracle dependency

function _recordSnapshotPair(uint256 eligibleUserPoolSize, uint256 eligibleHedgerPoolSize) internal;

Parameters

NameTypeDescription
eligibleUserPoolSizeuint256Eligible user-pool size to record (holding-period filtered)
eligibleHedgerPoolSizeuint256Eligible hedger-pool size to record

_recordPoolSnapshotWithEligibleSizes

Record pool snapshot using eligible pool sizes to prevent manipulation

SECURITY: Uses eligible pool sizes that respect holding period requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _recordPoolSnapshotWithEligibleSizes(uint256 eligibleUserPoolSize, uint256 eligibleHedgerPoolSize)
    internal;

Parameters

NameTypeDescription
eligibleUserPoolSizeuint256Eligible user pool size for yield calculations
eligibleHedgerPoolSizeuint256Eligible hedger pool size for yield calculations

_addToPoolHistory

Add pool snapshot to history

Adds a pool snapshot to the history array with size management

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _addToPoolHistory(PoolSnapshot[] storage poolHistory, uint256 poolSize, bool isUserPool, uint256 writePos)
    internal;

Parameters

NameTypeDescription
poolHistoryPoolSnapshot[]Array of pool snapshots to add to
poolSizeuint256Size of the pool to record
isUserPoolboolWhether this is for user pool or hedger pool
writePosuint256Ring-buffer slot to overwrite once the array is full (= count % MAX)

recoverToken

Recovers accidentally sent ERC20 tokens from the contract

Emergency function to recover tokens that are not part of normal operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressThe token address to recover
amountuint256The amount of tokens to recover

recoverETH

Recovers accidentally sent ETH from the contract

Emergency function to recover ETH that shouldn't be in the contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

Events

YieldDistributionUpdated

OPTIMIZED: Indexed timestamp for efficient time-based filtering

event YieldDistributionUpdated(
    uint256 newYieldShift, uint256 userYieldAllocation, uint256 hedgerYieldAllocation, uint256 indexed timestamp
);

HedgerYieldClaimed

event HedgerYieldClaimed(address indexed hedger, uint256 yieldAmount, uint256 timestamp);

YieldAdded

OPTIMIZED: Indexed source and timestamp for efficient filtering

event YieldAdded(uint256 yieldAmount, string indexed source, uint256 indexed timestamp);

SourceVaultBindingUpdated

event SourceVaultBindingUpdated(address indexed source, uint256 indexed vaultId);

SourceVaultBindingModeUpdated

event SourceVaultBindingModeUpdated(bool enabled);

Structs

PoolSnapshot

OPTIMIZED: Packed struct for gas efficiency in historical arrays

struct PoolSnapshot {
    uint128 userPoolSize;
    uint128 hedgerPoolSize;
    uint64 timestamp; // Timestamp (8 bytes, until year 2554)
}

YieldShiftSnapshot

OPTIMIZED: Packed struct for gas efficiency in yield shift tracking

struct YieldShiftSnapshot {
    uint128 yieldShift;
    uint64 timestamp; // Timestamp (8 bytes, until year 2554)
}

YieldModelConfig

struct YieldModelConfig {
    uint256 baseYieldShift;
    uint256 maxYieldShift;
    uint256 adjustmentSpeed;
    uint256 targetPoolRatio;
}

YieldDependencyConfig

struct YieldDependencyConfig {
    address userPool;
    address hedgerPool;
    address mockAaveVault;
    address stQEUROFactory;
    address treasury;
}

FeeCollector

Git Source

Inherits: AccessControlUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: FeeCollector

Author: Quantillon Protocol Team

Centralized fee collection and distribution contract for Quantillon Protocol

This contract handles all protocol fees from:

  • QEURO minting fees
  • QEURO redemption fees
  • Hedger position fees
  • Yield management fees
  • Other protocol operations

Features:

  • Centralized fee collection from all protocol contracts
  • Governance-controlled fee distribution
  • Multi-token fee support (USDC, QEURO, etc.)
  • Fee analytics and tracking
  • Emergency pause functionality
  • Upgradeable via UUPS proxy

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

Governance role for fee distribution and configuration

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

TREASURY_ROLE

Treasury role for fee withdrawal and distribution

bytes32 public constant TREASURY_ROLE = keccak256("TREASURY_ROLE")

FEE_SOURCE_ROLE

Separate role for authorized fee depositors (vault, hedger pool, etc.)

Distinct from TREASURY_ROLE so depositors cannot also withdraw/distribute fees

bytes32 public constant FEE_SOURCE_ROLE = keccak256("FEE_SOURCE_ROLE")

EMERGENCY_ROLE

Emergency role for pausing and emergency operations

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

State Variables

treasury

Treasury address for fee distribution

address public treasury

devFund

Protocol development fund address

address public devFund

communityFund

Community fund address

address public communityFund

authorizedETHRecipients

Whitelist mapping for authorized ETH recipients

Only whitelisted addresses can receive ETH transfers

mapping(address => bool) private authorizedETHRecipients

treasuryRatio

Fee distribution ratios (in basis points, 10000 = 100%)

uint256 public treasuryRatio

devFundRatio

uint256 public devFundRatio

communityRatio

uint256 public communityRatio

totalFeesCollected

Total fees collected per token

mapping(address => uint256) public totalFeesCollected

totalFeesDistributed

Total fees distributed per token

mapping(address => uint256) public totalFeesDistributed

feeCollectionCount

Fee collection events per token

mapping(address => uint256) public feeCollectionCount

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

onlyFeeSource

Ensures only authorized contracts can collect fees

modifier onlyFeeSource() ;

_onlyFeeSource

Reverts if caller is not an authorized fee source (governance, treasury, or whitelisted)

Used by onlyFeeSource modifier; checks GOVERNANCE_ROLE, TREASURY_ROLE, or _isAuthorizedFeeSource

Notes:

  • security: Access control only; no state change

  • validation: Caller must have fee-source role or be whitelisted

  • state-changes: None

  • events: None

  • errors: NotAuthorized if caller not authorized

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _onlyFeeSource() internal view;

constructor

Locks the implementation so it cannot be initialized directly

Disables initializers on the implementation contract; only proxies may be initialized. Brings FeeCollector in line with the other core contracts, which all call _disableInitializers().

Notes:

  • security: Prevents implementation-contract initialization

  • validation: No input validation required - constructor

  • state-changes: Disables initializers on the implementation

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - constructor

  • access: No access restrictions

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the FeeCollector contract

Sets up the initial configuration for fee collection and distribution

Sets up roles, fund addresses, and default fee distribution ratios

Notes:

  • security: Protected by initializer modifier

  • validation: Validates that all addresses are non-zero

  • state-changes: Sets up roles, fund addresses, and default ratios

  • events: Emits role grant events and FundAddressesUpdated event

  • errors: Throws ZeroAddress if any address is zero

  • reentrancy: No external calls, safe

  • access: Can only be called once during initialization

  • oracle: No oracle dependencies

function initialize(address _admin, address _treasury, address _devFund, address _communityFund)
    external
    initializer;

Parameters

NameTypeDescription
_adminaddressAdmin address (will receive DEFAULT_ADMIN_ROLE, GOVERNANCE_ROLE, and EMERGENCY_ROLE)
_treasuryaddressTreasury address (will receive TREASURY_ROLE)
_devFundaddressDev fund address (cannot be zero)
_communityFundaddressCommunity fund address (cannot be zero)

collectFees

Collects fees from protocol contracts

Transfers tokens from the caller to this contract and updates tracking variables

Only authorized fee sources can call this function

Emits FeesCollected event for transparency and analytics

Notes:

  • security: Protected by onlyFeeSource modifier and reentrancy guard

  • validation: Validates token address and amount parameters

  • state-changes: Updates totalFeesCollected and feeCollectionCount mappings

  • events: Emits FeesCollected event with collection details

  • errors: Throws InvalidAmount if amount is zero

  • errors: Throws ZeroAddress if token address is zero

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to authorized fee sources only

  • oracle: No oracle dependencies

function collectFees(address token, uint256 amount, string calldata sourceType)
    external
    onlyFeeSource
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
tokenaddressToken address to collect fees for (cannot be zero address)
amountuint256Amount of fees to collect (must be greater than zero)
sourceTypestringType of fee source (e.g., "minting", "redemption", "hedging")

collectETHFees

Collects ETH fees from protocol contracts

Accepts ETH payments and updates tracking variables for ETH (tracked as address(0))

Only authorized fee sources can call this function

Emits FeesCollected event for transparency and analytics

Notes:

  • security: Protected by onlyFeeSource modifier and reentrancy guard

  • validation: Validates that msg.value is greater than zero

  • state-changes: Updates totalFeesCollected and feeCollectionCount for address(0)

  • events: Emits FeesCollected event with ETH collection details

  • errors: Throws InvalidAmount if msg.value is zero

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to authorized fee sources only

  • oracle: No oracle dependencies

function collectETHFees(string calldata sourceType) external payable onlyFeeSource whenNotPaused nonReentrant;

Parameters

NameTypeDescription
sourceTypestringType of fee source (e.g., "staking", "governance", "liquidation")

distributeFees

Distributes collected fees according to configured ratios

Calculates distribution amounts based on treasuryRatio, devFundRatio, and communityRatio

Handles rounding by adjusting community amount to ensure total doesn't exceed balance

Only treasury role can call this function

Emits FeesDistributed event for transparency

Notes:

  • security: Protected by TREASURY_ROLE and reentrancy guard

  • validation: Validates that contract has sufficient balance

  • state-changes: Updates totalFeesDistributed and transfers tokens to fund addresses

  • events: Emits FeesDistributed event with distribution details

  • errors: Throws InsufficientBalance if contract balance is zero

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to TREASURY_ROLE only

  • oracle: No oracle dependencies

function distributeFees(address token) external onlyRole(TREASURY_ROLE) whenNotPaused nonReentrant;

Parameters

NameTypeDescription
tokenaddressToken address to distribute (address(0) for ETH)

_calculateDistributionAmounts

Calculate distribution amounts with rounding protection

Internal function to reduce cyclomatic complexity

Notes:

  • security: No external calls, pure calculation function

  • validation: Balance must be non-zero for meaningful distribution

  • state-changes: No state changes, view function

  • events: No events emitted

  • errors: No custom errors, uses SafeMath for overflow protection

  • reentrancy: No reentrancy risk, view function

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _calculateDistributionAmounts(uint256 balance)
    internal
    view
    returns (uint256 treasuryAmount, uint256 devFundAmount, uint256 communityAmount);

Parameters

NameTypeDescription
balanceuint256Total balance to distribute

Returns

NameTypeDescription
treasuryAmountuint256Amount for treasury
devFundAmountuint256Amount for dev fund
communityAmountuint256Amount for community fund

_executeTransfers

Execute transfers for ETH or ERC20 tokens

Internal function to reduce cyclomatic complexity

Notes:

  • security: Delegates to specific transfer functions with proper validation

  • validation: Amounts must be non-zero for transfers to execute

  • state-changes: Updates token balances through transfers

  • events: No direct events, delegated functions emit events

  • errors: May revert on transfer failures

  • reentrancy: Protected by internal function design

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _executeTransfers(address token, uint256 treasuryAmount, uint256 devFundAmount, uint256 communityAmount)
    internal;

Parameters

NameTypeDescription
tokenaddressToken address (address(0) for ETH)
treasuryAmountuint256Amount for treasury
devFundAmountuint256Amount for dev fund
communityAmountuint256Amount for community fund

_executeETHTransfers

Execute ETH transfers

Internal function to reduce cyclomatic complexity

Notes:

  • security: Uses secure ETH transfer with address validation

  • validation: Amounts must be non-zero for transfers to execute

  • state-changes: Reduces contract ETH balance, increases recipient balances

  • events: No direct events emitted

  • errors: Reverts with ETHTransferFailed on call failure

  • reentrancy: Protected by internal function design and address validation

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _executeETHTransfers(uint256 treasuryAmount, uint256 devFundAmount, uint256 communityAmount) internal;

Parameters

NameTypeDescription
treasuryAmountuint256Amount for treasury
devFundAmountuint256Amount for dev fund
communityAmountuint256Amount for community fund

_secureETHTransfer

Secure ETH transfer with comprehensive validation

Validates recipient address against whitelist and performs secure ETH transfer

Notes:

  • security: Multiple validation layers prevent arbitrary sends:

  • Recipient must be one of three pre-authorized fund addresses

  • Addresses are validated to be non-zero; contract wallets are supported

  • Only GOVERNANCE_ROLE can update these addresses

  • This is NOT an arbitrary send as recipient is strictly controlled

  • validation: Ensures recipient is valid and amount is positive

  • state-changes: Transfers ETH from contract to recipient

  • events: No events emitted

  • errors: Reverts with ETHTransferFailed on transfer failure

  • reentrancy: Protected by address validation and call pattern

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _secureETHTransfer(address recipient, uint256 amount) internal;

Parameters

NameTypeDescription
recipientaddressAddress to receive ETH (must be treasury, devFund, or communityFund)
amountuint256Amount of ETH to transfer

_executeERC20Transfers

Execute ERC20 token transfers

Internal function to reduce cyclomatic complexity

Notes:

  • security: Uses safeTransfer for ERC20 tokens with proper error handling

  • validation: Amounts must be non-zero for transfers to execute

  • state-changes: Reduces contract token balance, increases recipient balances

  • events: No direct events emitted

  • errors: May revert on transfer failures from ERC20 contract

  • reentrancy: Protected by internal function design and safeTransfer

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _executeERC20Transfers(
    address token,
    uint256 treasuryAmount,
    uint256 devFundAmount,
    uint256 communityAmount
) internal;

Parameters

NameTypeDescription
tokenaddressToken address
treasuryAmountuint256Amount for treasury
devFundAmountuint256Amount for dev fund
communityAmountuint256Amount for community fund

updateFeeRatios

Updates fee distribution ratios

Sets new distribution ratios for treasury, dev fund, and community fund

Ratios must sum to exactly 10000 (100%) in basis points

Only governance role can call this function

Emits FeeRatiosUpdated event for transparency

Notes:

  • security: Protected by GOVERNANCE_ROLE

  • validation: Validates that ratios sum to exactly 10000

  • state-changes: Updates treasuryRatio, devFundRatio, and communityRatio

  • events: Emits FeeRatiosUpdated event with new ratios

  • errors: Throws InvalidRatio if ratios don't sum to 10000

  • reentrancy: No external calls, safe

  • access: Restricted to GOVERNANCE_ROLE only

  • oracle: No oracle dependencies

function updateFeeRatios(uint256 _treasuryRatio, uint256 _devFundRatio, uint256 _communityRatio)
    external
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryRatiouint256New treasury ratio (in basis points, 10000 = 100%)
_devFundRatiouint256New dev fund ratio (in basis points, 10000 = 100%)
_communityRatiouint256New community ratio (in basis points, 10000 = 100%)

updateFundAddresses

Updates fund addresses for fee distribution

Sets new addresses for treasury, dev fund, and community fund

All addresses must be non-zero

Only governance role can call this function

Emits FundAddressesUpdated event for transparency

Notes:

  • security: Protected by GOVERNANCE_ROLE

  • validation: Validates that all addresses are non-zero

  • state-changes: Updates treasury, devFund, and communityFund addresses

  • events: Emits FundAddressesUpdated event with new addresses

  • errors: Throws ZeroAddress if any address is zero

  • reentrancy: No external calls, safe

  • access: Restricted to GOVERNANCE_ROLE only

  • oracle: No oracle dependencies

function updateFundAddresses(address _treasury, address _devFund, address _communityFund)
    external
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address (cannot be zero)
_devFundaddressNew dev fund address (cannot be zero)
_communityFundaddressNew community fund address (cannot be zero)

authorizeFeeSource

Authorizes a contract to collect fees

Grants TREASURY_ROLE to the specified address, allowing it to collect fees

Only governance role can call this function

Notes:

  • security: Protected by GOVERNANCE_ROLE

  • validation: Validates that feeSource is not zero address

  • state-changes: Grants TREASURY_ROLE to feeSource

  • events: Emits RoleGranted event for TREASURY_ROLE

  • errors: Throws ZeroAddress if feeSource is zero

  • reentrancy: No external calls, safe

  • access: Restricted to GOVERNANCE_ROLE only

  • oracle: No oracle dependencies

function authorizeFeeSource(address feeSource) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
feeSourceaddressContract address to authorize (cannot be zero)

revokeFeeSource

Revokes fee collection authorization

Revokes TREASURY_ROLE from the specified address, preventing it from collecting fees

Only governance role can call this function

Notes:

  • security: Protected by GOVERNANCE_ROLE

  • validation: No validation required (can revoke from any address)

  • state-changes: Revokes TREASURY_ROLE from feeSource

  • events: Emits RoleRevoked event for TREASURY_ROLE

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Restricted to GOVERNANCE_ROLE only

  • oracle: No oracle dependencies

function revokeFeeSource(address feeSource) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
feeSourceaddressContract address to revoke authorization from

pause

Pauses fee collection and distribution

Emergency function to pause all fee operations in case of security issues

Only emergency role can call this function

Notes:

  • security: Protected by EMERGENCY_ROLE

  • validation: No validation required

  • state-changes: Sets paused state to true

  • events: Emits Paused event

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Restricted to EMERGENCY_ROLE only

  • oracle: No oracle dependencies

function pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpauses fee collection and distribution

Resumes all fee operations after a pause

Only emergency role can call this function

Notes:

  • security: Protected by EMERGENCY_ROLE

  • validation: No validation required

  • state-changes: Sets paused state to false

  • events: Emits Unpaused event

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Restricted to EMERGENCY_ROLE only

  • oracle: No oracle dependencies

function unpause() external onlyRole(EMERGENCY_ROLE);

emergencyWithdraw

Emergency withdrawal of all tokens (only in extreme circumstances)

Emergency function to withdraw all tokens to treasury in case of critical issues

Only emergency role can call this function

Notes:

  • security: Protected by EMERGENCY_ROLE

  • validation: Validates that contract has sufficient balance

  • state-changes: Transfers all tokens to treasury address

  • events: No custom events (uses standard transfer events)

  • errors: Throws InsufficientBalance if contract balance is zero

  • errors: Throws ETHTransferFailed if ETH transfer fails

  • reentrancy: No external calls, safe

  • access: Restricted to EMERGENCY_ROLE only

  • oracle: No oracle dependencies

function emergencyWithdraw(address token) external onlyRole(EMERGENCY_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to withdraw (address(0) for ETH)

getBalance

Returns the current balance of a token

Returns the current balance of the specified token held by this contract

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getBalance(address token) external view returns (uint256);

Parameters

NameTypeDescription
tokenaddressToken address (address(0) for ETH)

Returns

NameTypeDescription
<none>uint256Current balance of the token in this contract

getFeeStats

Returns fee collection statistics for a token

Returns comprehensive statistics about fee collection and distribution for a specific token

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getFeeStats(address token)
    external
    view
    returns (uint256 totalCollected, uint256 totalDistributed, uint256 collectionCount, uint256 currentBalance);

Parameters

NameTypeDescription
tokenaddressToken address (address(0) for ETH)

Returns

NameTypeDescription
totalCollecteduint256Total amount of fees collected for this token
totalDistributeduint256Total amount of fees distributed for this token
collectionCountuint256Number of fee collection transactions for this token
currentBalanceuint256Current balance of this token in the contract

isAuthorizedFeeSource

Checks if an address is authorized to collect fees

Returns whether the specified address has permission to collect fees

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function isAuthorizedFeeSource(address feeSource) external view returns (bool);

Parameters

NameTypeDescription
feeSourceaddressAddress to check for authorization

Returns

NameTypeDescription
<none>boolTrue if the address is authorized to collect fees, false otherwise

_isAuthorizedFeeSource

Internal function to check if an address is authorized to collect fees

Internal helper function to check TREASURY_ROLE for fee collection authorization

Notes:

  • security: Internal function, no direct security implications

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (internal function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Internal function only

  • oracle: No oracle dependencies

function _isAuthorizedFeeSource(address feeSource) internal view returns (bool);

Parameters

NameTypeDescription
feeSourceaddressAddress to check for authorization

Returns

NameTypeDescription
<none>boolTrue if the address has TREASURY_ROLE, false otherwise

_authorizeUpgrade

Authorizes upgrades (only governance)

Internal function to authorize contract upgrades via UUPS proxy pattern

Only governance role can authorize upgrades

Notes:

  • security: Protected by GOVERNANCE_ROLE

  • validation: No validation required (OpenZeppelin handles this)

  • state-changes: No state changes (authorization only)

  • events: No custom events (OpenZeppelin handles upgrade events)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Restricted to GOVERNANCE_ROLE only

  • oracle: No oracle dependencies

function _authorizeUpgrade(address newImplementation) internal override onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract

Events

FeesCollected

Emitted when fees are collected

event FeesCollected(address indexed token, uint256 amount, address indexed source, string indexed sourceType);

FeesDistributed

Emitted when fees are distributed

event FeesDistributed(
    address indexed token,
    uint256 totalAmount,
    uint256 treasuryAmount,
    uint256 devFundAmount,
    uint256 communityAmount
);

FeeRatiosUpdated

Emitted when fee distribution ratios are updated

event FeeRatiosUpdated(uint256 treasuryRatio, uint256 devFundRatio, uint256 communityRatio);

FundAddressesUpdated

Emitted when fund addresses are updated

event FundAddressesUpdated(address treasury, address devFund, address communityFund);

HedgerPool

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IVersioned

Title: HedgerPool

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Optimized EUR/USD hedging pool for managing currency risk and providing yield

Optimized version with reduced contract size through library extraction and code consolidation P&L Calculation Model: Hedgers are SHORT EUR. FilledVolume is the remaining QEURO's original USDC cost. unrealizedPnL = FilledVolume - (QEUROBacked * OraclePrice / 1e30). effectiveMargin = margin + unrealizedPnL. A redemption releases proportional original cost and realizes releasedCost - payout into margin. realizedPnL is cumulative history only; it does not value remaining exposure. Liquidation redemptions reduce margin and remaining cost proportionally.

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

TIME_PROVIDER

TimeProvider public immutable TIME_PROVIDER

MAX_REWARD_FEE_SPLIT

Maximum allowed value for rewardFeeSplit

uint256 public constant MAX_REWARD_FEE_SPLIT = 1e18

MAX_UINT96_VALUE

uint96 public constant MAX_UINT96_VALUE = type(uint96).max

MAX_POSITION_SIZE

uint256 public constant MAX_POSITION_SIZE = MAX_UINT96_VALUE

MAX_MARGIN

uint256 public constant MAX_MARGIN = MAX_UINT96_VALUE

MAX_ENTRY_PRICE

uint256 public constant MAX_ENTRY_PRICE = MAX_UINT96_VALUE

MAX_LEVERAGE

uint256 public constant MAX_LEVERAGE = type(uint16).max

MAX_MARGIN_RATIO

uint256 public constant MAX_MARGIN_RATIO = 5000

DEFAULT_MIN_MARGIN_RATIO_BPS

Governance floor for coreParams.minMarginRatio: configureRiskAndFees cannot set the minimum margin ratio below 250 bps (2.5% of exposure). The launch default written by initialize stays 500 bps (5%); lowering the live value toward this floor is an explicit governance decision (margin-rebalancing target, 2026-09).

uint256 public constant DEFAULT_MIN_MARGIN_RATIO_BPS = 250

MAX_CONFIGURABLE_LEVERAGE

Ceiling for coreParams.maxLeverage accepted by configureRiskAndFees. A position's margin ratio is 10000 / leverage bps, so the leverage implied by the DEFAULT_MIN_MARGIN_RATIO_BPS floor is 10000 / 250 = 40x. The setter previously capped leverage at 20x, which contradicted that floor: a 2.5% margin ratio was permitted by validateMarginRatio and by the collateral-based fill capacity, but could not be configured or opened. This constant realigns the two bounds.

uint256 public constant MAX_CONFIGURABLE_LEVERAGE = 40

MAX_UINT128_VALUE

uint128 public constant MAX_UINT128_VALUE = type(uint128).max

MAX_TOTAL_MARGIN

uint256 public constant MAX_TOTAL_MARGIN = MAX_UINT128_VALUE

MAX_TOTAL_EXPOSURE

uint256 public constant MAX_TOTAL_EXPOSURE = MAX_UINT128_VALUE

MAX_REWARD_PERIOD

uint256 public constant MAX_REWARD_PERIOD = 365 days

QEURO_DUST_THRESHOLD

QEURO amounts (18 decimals) at or below this are treated as unredeemable rounding dust

Proportional round-down on redemptions/unstakes can strand a few wei of QEURO supply or per-position backing that nobody can redeem (e.g. inside a stQEURO vault whose share supply is zero). Exact-zero guards on those values dead-lock hedger exits and full margin withdrawal forever. 1e12 wei = 1e-6 QEURO, worth at most ~one USDC unit (6 decimals) — economically indistinguishable from zero while 30 orders of magnitude below real supply.

uint256 public constant QEURO_DUST_THRESHOLD = 1e12

State Variables

usdc

IERC20 public usdc

oracle

IOracle public oracle

yieldShift

IYieldShift public yieldShift

vault

IQuantillonVault public vault

treasury

address public treasury

coreParams

CoreParams public coreParams

totalMargin

uint256 public totalMargin

totalExposure

uint256 public totalExposure

totalFilledExposure

uint256 public totalFilledExposure

singleHedger

Address of the single hedger allowed to open positions

This replaces the previous multi-hedger whitelist model

ARCHITECTURAL CONSTRAINT — Only one hedger can exist at a time. If the single hedger exits or becomes unavailable, the protocol's hedging guarantee collapses. Multi-hedger support requires a protocol redesign.

address public singleHedger

minPositionHoldBlocks

Minimum blocks a position must be held before closing (~60s on mainnet)

uint256 public minPositionHoldBlocks = 5

minMarginAmount

Minimum USDC margin required to open a position (prevents dust / unliquidatable positions)

uint256 public minMarginAmount = 100e6

pendingRewardWithdrawals

Pending reward withdrawals for hedgers whose direct transfer failed (e.g. USDC blacklist)

mapping(address => uint256) public pendingRewardWithdrawals

feeCollector

Address of the FeeCollector that receives margin fees

address public feeCollector

rewardFeeSplit

Share of protocol fees routed to the local reward reserve (1e18 = 100%)

uint256 public rewardFeeSplit

__deprecated_pendingSingleHedger

Vestigial: retained as private to preserve the live proxy storage layout; the public getters were removed (dead — never set/read).

address private __deprecated_pendingSingleHedger

__deprecated_singleHedgerPendingAt

uint256 private __deprecated_singleHedgerPendingAt

positions

mapping(uint256 => HedgePosition) public positions

hedgerRewards

mapping(address => HedgerRewardState) private hedgerRewards

hedgerActivePositionId

Maps hedger address to their active position ID (0 = no active position)

Used to track the single hedger's position in single hedger model

mapping(address => uint256) private hedgerActivePositionId

hedgerLastRewardBlock

mapping(address => uint256) public hedgerLastRewardBlock

costBasisAccountingInitialized

Whether remaining-cost accounting has been initialized for this proxy.

Appended storage; existing proxies must activate while paused and fully settled.

bool public costBasisAccountingInitialized

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

executeWithReference

Execute a hedger operation with an atomically refreshed signed reference.

The linked library preserves msg.sender and uses the governed oracle binding.

Notes:

  • security: Only enter, exit, remove-margin and emergency-close selectors are allowed.

  • validation: Source signature, original observation age and existing operation guards.

  • state-changes: Reference cache and the selected operation's normal accounting.

  • events: ReferenceAccepted and existing operation events.

  • errors: Propagates reference validation and operation errors atomically.

  • reentrancy: The selected operation retains its nonReentrant modifier.

  • access: The selected operation checks the original caller's permissions.

  • oracle: Signed reference via the active market oracle; no execution quote consumed.

function executeWithReference(bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesComplete calldata of the allowed hedger operation.
authorizationbytesABI-encoded reference report and signature.

Returns

NameTypeDescription
resultbytesThe selected operation's return data.

removeMarginWithReference

Withdraw margin with a signed reference in one atomic transaction.

Typed parameters let Roles constrain the position and amount without authorizing arbitrary calldata.

Notes:

  • security: Preserves caller identity and all removeMargin guards.

  • validation: Validated reference, ownership, collateralization and withdrawal bounds.

  • state-changes: Reference and margin accounting revert together on failure.

  • events: ReferenceAccepted and margin withdrawal events.

  • errors: Propagates source validation and removeMargin errors.

  • reentrancy: removeMargin retains its nonReentrant guard.

  • access: Position owner; adds no withdrawal authority.

  • oracle: Governed signed reference source, submitted within this transaction.

function removeMarginWithReference(uint256 positionId, uint256 amount, bytes calldata authorization)
    external
    returns (bytes memory);

Parameters

NameTypeDescription
positionIduint256Position owned by the caller.
amountuint256USDC margin to withdraw, in 6 decimals.
authorizationbytesABI-encoded reference report and signature.

Returns

NameTypeDescription
<none>bytesABI-encoded result of the underlying withdrawal (empty on success).

onlyVault

modifier onlyVault() ;

onlySelf

modifier onlySelf() ;

_onlySelf

Reverts unless caller is this contract.

Internal guard used by onlySelf commit helpers invoked via explicit self-calls.

Notes:

  • security: Prevents direct external invocation of self-call commit paths.

  • validation: Requires msg.sender == address(this).

  • state-changes: None.

  • events: None.

  • errors: Reverts with NotAuthorized when caller is not self.

  • reentrancy: No external calls.

  • access: Internal helper used by modifier.

  • oracle: No oracle dependencies.

function _onlySelf() internal view;

_onlyVault

Reverts if caller is not the vault contract

Used by onlyVault modifier; restricts vault-only callbacks (e.g. realized P&L)

Notes:

  • security: Access control for vault callbacks

  • validation: msg.sender must equal vault

  • state-changes: None

  • events: None

  • errors: OnlyVault if caller not vault

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _onlyVault() internal view;

constructor

Initializes the HedgerPool contract with a time provider

Constructor that sets up the time provider and disables initializers for upgrade safety

Notes:

  • security: Validates that the time provider is not zero address

  • validation: Ensures TIME_PROVIDER is a valid contract address

  • state-changes: Sets TIME_PROVIDER and disables initializers

  • events: None

  • errors: Throws ZeroAddress if _TIME_PROVIDER is address(0)

  • reentrancy: Not applicable - constructor

  • access: Public constructor

  • oracle: Not applicable

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderThe time provider contract for timestamp management

_protocolTime

Returns canonical protocol time from this contract's TimeProvider

Overrides the SecureUpgradeable base, which returns block.timestamp.

Notes:

  • security: Reads the immutable TimeProvider set at construction

  • validation: None required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Canonical protocol time in seconds

initialize

Initializes the HedgerPool with contracts and parameters

This function configures:

  1. Access roles and permissions
  2. References to external contracts
  3. Default protocol parameters
  4. Security (pause, reentrancy, upgrades)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Initializes all contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by initializer modifier

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address _usdc,
    address _oracle,
    address _yieldShift,
    address _timelock,
    address _treasury,
    address _vault
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_usdcaddressAddress of the USDC token contract
_oracleaddressAddress of the Oracle contract
_yieldShiftaddressAddress of the YieldShift contract
_timelockaddressAddress of the timelock contract
_treasuryaddressAddress of the treasury contract
_vaultaddressAddress of the QuantillonVault contract

initializeCostBasisAccounting

Activates remaining-cost accounting on a settled, paused proxy.

Existing positions must be reconciled and closed before upgrading. Fresh deployments activate in initialize. No active balances are converted by this entry point.

Notes:

  • security: Governance-only, one-time activation with no outstanding exposure.

  • validation: Requires no active position, margin, exposure, or QEURO above dust.

  • state-changes: Sets the accounting initialization flag and initializer version.

  • events: Emits Initialized through reinitializer.

  • errors: InvalidPosition if settlement or activation preconditions are not met.

  • reentrancy: No state-changing external calls.

  • access: GOVERNANCE_ROLE while paused.

  • oracle: No oracle dependencies.

function initializeCostBasisAccounting() external reinitializer(2) whenPaused;

_requireCostBasisAccounting

Requires the accounting model to be initialized before reading or settling exposure.

Prevents an existing proxy from interpreting unsettled position balances as remaining cost.

Notes:

  • security: Blocks financial accounting until explicit activation.

  • validation: Checks the appended initialization flag.

  • state-changes: None.

  • events: None.

  • errors: InvalidPosition before activation.

  • reentrancy: No external calls.

  • access: Internal.

  • oracle: No oracle dependencies.

function _requireCostBasisAccounting() private view;

enterHedgePosition

Opens a new hedge position for a hedger

Position opening process:

  1. Enforces single hedger access
  2. Fetches current EUR/USD price from oracle
  3. Calculates position size and validates parameters
  4. Transfers USDC to vault for unified liquidity
  5. Creates position record and updates hedger stats

Security features:

  1. Flash loan protection via secureNonReentrant
  2. Single-hedger gate
  3. Parameter validation (leverage, amounts)
  4. Oracle price validation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates amount > 0, leverage within limits, and active single hedger

  • state-changes: Creates new position, updates hedger stats, transfers USDC to vault

  • events: Emits HedgePositionOpened with position details

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by secureNonReentrant modifier and proper CEI pattern

  • access: Restricted to configured single hedger

  • oracle: Requires fresh oracle price data

function enterHedgePosition(uint256 usdcAmount, uint256 leverage)
    external
    whenNotPaused
    nonReentrant
    returns (uint256 positionId);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit as margin (6 decimals)
leverageuint256Leverage multiplier for the position (1-20x)

Returns

NameTypeDescription
positionIduint256Unique identifier for the new position

_enterHedgePositionCommit

Commits single-hedger position opening state and interactions

Called via this._enterHedgePositionCommit(...) from enterHedgePosition after checks/calculation phase.

Notes:

  • security: Self-call gate (onlySelf) ensures this function cannot be invoked directly by external callers

  • validation: Assumes upstream validation already enforced bounds and authorization

  • state-changes: Writes position storage, hedger active position pointer, and aggregate margin/exposure totals

  • events: Emits HedgePositionOpened

  • errors: Token/vault calls may revert and bubble up errors

  • reentrancy: Executed from nonReentrant parent; follows checks/effects/interactions split

  • access: External function restricted to self-call path

  • oracle: No direct oracle dependency (uses pre-validated input price)

function _enterHedgePositionCommit(
    address hedger,
    uint256 usdcAmount,
    uint256 leverage,
    uint256 currentTime,
    uint256 eurUsdPrice,
    uint256 netMargin,
    uint256 positionSize
) external onlySelf returns (uint256 positionId);

Parameters

NameTypeDescription
hedgeraddressHedger address opening the position
usdcAmountuint256USDC principal transferred from hedger to vault
leverageuint256Leverage selected for the position
currentTimeuint256Current protocol timestamp used for position timing fields
eurUsdPriceuint256Validated EUR/USD price used as entry price
netMarginuint256Net margin after entry fee deduction
positionSizeuint256Position notional derived from margin and leverage

Returns

NameTypeDescription
positionIduint256Created position identifier (single-position model => 1)

_packHedgeEventData

Packs position fields into the bytes32 carried by hedge-position events

Layout (MSB->LSB): [255:160] positionSize (uint96) | [159:64] margin (uint96) | [63:48] leverage (uint16) | [47:0] reserved. Used by HedgePositionOpened, HedgePositionClosed and MarginUpdated so indexers can read position state from the event.

Notes:

  • security: No security implications - pure bit-packing of already-validated values

  • validation: No validation - caller supplies struct-typed values

  • state-changes: None - pure function

  • events: None

  • errors: None

  • reentrancy: Not applicable - pure function

  • access: Internal - no access restrictions

  • oracle: Not applicable - no oracle dependency

function _packHedgeEventData(uint96 positionSize_, uint96 margin_, uint16 leverage_)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
positionSize_uint96Position size to pack (uint96)
margin_uint96Margin to pack (uint96)
leverage_uint16Leverage to pack (uint16)

Returns

NameTypeDescription
<none>bytes32Packed bytes32 event payload

_initializeOpenedPosition

function _initializeOpenedPosition(
    HedgePosition storage position,
    address hedger,
    uint256 positionSize,
    uint256 netMargin,
    uint256 currentTime,
    uint256 leverage,
    uint256 eurUsdPrice
) private;

exitHedgePosition

Closes an existing hedge position

Position closing process:

  1. Validates position ownership and active status
  2. Checks protocol collateralization safety
  3. Calculates current PnL based on price change
  4. Determines net payout to hedger
  5. Updates hedger stats and removes position
  6. Withdraws USDC from vault for hedger payout

Security features:

  1. Position ownership validation
  2. Protocol collateralization safety check
  3. Pause protection

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates position ownership, active status, and protocol safety

  • state-changes: Closes position, updates hedger stats, withdraws USDC from vault

  • events: Emits HedgePositionClosed with position details

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to position owner

  • oracle: Requires fresh oracle price data

function exitHedgePosition(uint256 positionId) external whenNotPaused nonReentrant returns (int256 pnl);

Parameters

NameTypeDescription
positionIduint256Unique identifier of the position to close

Returns

NameTypeDescription
pnlint256Profit or loss from the position (positive = profit, negative = loss)

_exitHedgePositionCommit

function _exitHedgePositionCommit(address hedger, uint256 positionId) private returns (int256 pnl);

addMargin

Adds additional margin to an existing hedge position

Margin addition process:

  1. Validates position ownership and active status
  2. Validates amount is positive
  3. Checks liquidation cooldown and pending liquidation status
  4. Transfers USDC from hedger to vault
  5. Updates position margin and hedger stats

Security features:

  1. Flash loan protection
  2. Position ownership validation
  3. Liquidation cooldown validation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates position ownership, active status, positive amount, liquidation cooldown

  • state-changes: Updates position margin, hedger stats, transfers USDC to vault

  • events: Emits MarginAdded with position details

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to position owner

  • oracle: No oracle dependencies

function addMargin(uint256 positionId, uint256 amount) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
positionIduint256Unique identifier of the position
amountuint256Amount of USDC to add as margin (6 decimals)

_routeHedgeFee

Routes a hedge fee between the HedgerPool reward reserve and the FeeCollector

Shared by addMargin, position entry, and position exit so every hedge-fee path routes identically. The reserve share physically remains in this contract's USDC balance (the reward reserve); the collector share is forwarded to the FeeCollector. Assumes the gross fee USDC is already held by this contract.

Notes:

  • security: Moves already-collected fee USDC only; no authority change

  • validation: No-op when fee is zero

  • state-changes: Increases FeeCollector allowance; reserve share stays as USDC balance

  • events: Emits RewardReserveFunded for the reserve share

  • errors: Propagates FeeCollector failures

  • reentrancy: Called within nonReentrant flows

  • access: Private helper

  • oracle: No oracle dependency

function _routeHedgeFee(address funder, uint256 fee, string memory sourceType) private;

Parameters

NameTypeDescription
funderaddressAddress credited as the reserve funder in the emitted event
feeuint256Total fee amount in USDC (6 decimals)
sourceTypestringSource tag forwarded to FeeCollector accounting

removeMargin

Removes margin from an existing hedge position

Margin removal process:

  1. Validates position ownership and active status
  2. Validates amount is positive
  3. Validates margin operation maintains minimum margin ratio
  4. Updates position margin and hedger stats
  5. Withdraws USDC from vault to hedger

Security features:

  1. Flash loan protection
  2. Position ownership validation
  3. Minimum margin ratio validation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates position ownership, active status, positive amount, minimum margin ratio

  • state-changes: Updates position margin, hedger stats, withdraws USDC from vault

  • events: Emits MarginUpdated with position details

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to position owner

  • oracle: No oracle dependencies

function removeMargin(uint256 positionId, uint256 amount) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
positionIduint256Unique identifier of the position
amountuint256Amount of USDC to remove from margin (6 decimals)

_validatePositionHealthAfterMarginRemoval

function _validatePositionHealthAfterMarginRemoval(HedgePosition storage position, uint256 newMargin) private;

_removeMarginCommit

function _removeMarginCommit(
    uint256 positionId,
    uint256 newMargin,
    uint256 newPositionSize,
    uint256 deltaPositionSize,
    uint256 amount
) private;

recordUserMint

Records a user mint and allocates hedger fills proportionally

Callable only by QuantillonVault to sync hedger exposure with user activity

Notes:

  • security: Only callable by the vault; amount must be positive

  • validation: Validates the amount and price are greater than zero

  • state-changes: Updates total filled exposure and per-position fills

  • events: None

  • errors: Reverts with InvalidAmount, InvalidOraclePrice, NoActiveHedgerLiquidity, or InsufficientHedgerCapacity

  • reentrancy: Not applicable (no external calls besides trusted helpers)

  • access: Restricted to QuantillonVault

  • oracle: Uses provided price to avoid duplicate oracle calls

function recordUserMint(uint256 usdcAmount, uint256 fillPrice, uint256 qeuroAmount)
    external
    onlyVault
    whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Net USDC amount that was minted into QEURO (6 decimals)
fillPriceuint256EUR/USD oracle price (18 decimals) observed by the vault
qeuroAmountuint256QEURO amount that was minted (18 decimals)

recordUserRedeem

Records a user redemption and releases hedger fills proportionally

Callable only by QuantillonVault to sync hedger exposure with user activity

Notes:

  • security: Only callable by the vault; amount must be positive

  • validation: Validates the amount and price are greater than zero

  • state-changes: Reduces total filled exposure and per-position fills

  • events: None

  • errors: Reverts with InvalidAmount, InvalidOraclePrice, or InsufficientHedgerCapacity

  • reentrancy: Not applicable (no external calls besides trusted helpers)

  • access: Restricted to QuantillonVault

  • oracle: Uses provided price to avoid duplicate oracle calls

function recordUserRedeem(uint256 usdcAmount, uint256 redeemPrice, uint256 qeuroAmount)
    external
    onlyVault
    whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Gross USDC amount redeemed from QEURO burn (6 decimals)
redeemPriceuint256EUR/USD oracle price (18 decimals) observed by the vault
qeuroAmountuint256QEURO amount that was redeemed (18 decimals)

recordLiquidationRedeem

Records a liquidation mode redemption - directly reduces hedger margin proportionally

Called by vault when protocol is in liquidation mode (CR ≤ 101%) In liquidation mode, the ENTIRE hedger margin is considered at risk (unrealized P&L = -margin). When users redeem, the hedger absorbs a pro-rata loss: Formula: hedgerLoss = (qeuroAmount / totalQeuroSupply) × currentMargin This loss is recorded as realized P&L and reduces the hedger's margin. The qeuroBacked and filledVolume are also reduced proportionally.

Notes:

  • security: Vault-only access prevents unauthorized calls

  • validation: Validates qeuroAmount > 0, totalQeuroSupply > 0, position exists and is active

  • state-changes: Reduces hedger margin, records realized P&L, reduces qeuroBacked and filledVolume

  • events: Emits MarginUpdated when realized losses/profits modify margin

  • errors: None (early returns for invalid states)

  • reentrancy: Protected by whenNotPaused modifier

  • access: Restricted to QuantillonVault via onlyVault modifier

  • oracle: No oracle dependency - uses provided parameters

function recordLiquidationRedeem(uint256 qeuroAmount, uint256 totalQeuroSupply) external onlyVault whenNotPaused;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO being redeemed (18 decimals)
totalQeuroSupplyuint256Total QEURO supply before redemption (18 decimals)

claimHedgingRewards

Claims hedging rewards for a hedger

Reward claiming process:

  1. Calculates interest differential based on exposure and rates
  2. Settles YieldShift rewards directly via yieldShift.claimHedgerYield
  3. Updates hedger's last reward block
  4. Pays interest-differential rewards from HedgerPool reserve (or escrows into pendingRewardWithdrawals if transfer cannot complete)

Security features:

  1. Reentrancy protection
  2. Single-source settlement for YieldShift rewards (no double counting)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Caller must be configured singleHedger

  • state-changes: Updates hedger reward tracking and reward escrow state

  • events: None (the HedgingRewardsClaimed event was removed in v1.0.1)

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to configured single hedger

  • oracle: No oracle dependencies

function claimHedgingRewards()
    external
    nonReentrant
    returns (uint256 interestDifferential, uint256 yieldShiftRewards, uint256 totalRewards);

Returns

NameTypeDescription
interestDifferentialuint256Interest differential rewards earned
yieldShiftRewardsuint256Yield shift rewards earned
totalRewardsuint256Total rewards claimed

withdrawPendingRewards

Withdraw rewards that could not be pushed due to USDC transfer failure (e.g. blacklist)

Pull-based fallback for hedgers whose push transfer failed in claimHedgingRewards. Uses the pendingRewardWithdrawals mapping as a per-hedger escrow and sends the entire pending amount to the provided recipient address.

Notes:

  • security: Protected by nonReentrant and SafeERC20; only the hedger (msg.sender) can withdraw their own pending rewards.

  • validation: Reverts if recipient is the zero address or the caller has no pending rewards recorded.

  • state-changes: Reduces pendingRewardWithdrawals[msg.sender] by the paid amount and transfers that USDC to recipient.

  • events: No events emitted; off-chain indexers should track pendingRewardWithdrawals and standard ERC20 Transfer events.

  • errors: Reverts with ZeroAddress when recipient is zero, InvalidAmount when there is no pending reward, and InsufficientBalance when the reward reserve is currently empty; SafeERC20 may bubble up token errors.

  • reentrancy: Protected by nonReentrant; external interaction is a single USDC transfer.

  • access: External function callable by any hedger for their own pending rewards only.

  • oracle: No oracle dependencies.

function withdrawPendingRewards(address recipient) external nonReentrant;

Parameters

NameTypeDescription
recipientaddressAddress that will receive the pending rewards; allows a blacklisted hedger to specify an alternative, non-blacklisted address.

getTotalEffectiveHedgerCollateral

Calculates total effective hedger collateral (margin + P&L) for the hedger position

Used by vault to determine protocol collateralization ratio Formula breakdown:

  1. unrealizedPnL = remainingCost - (qeuroBacked * price / 1e30).
  2. effectiveCollateral = margin + unrealizedPnL, floored at zero. Realized P&L is already included in margin. An unfilled position retains its margin.

Notes:

  • security: View-only helper - no state changes, safe for external calls

  • validation: Validates price > 0, position exists and is active

  • state-changes: None - view function

  • events: None - view function

  • errors: None - returns 0 for invalid states

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query effective collateral

  • oracle: Takes the EUR/USD price as a parameter; caller must supply fresh oracle data

function getTotalEffectiveHedgerCollateral(uint256 price) external view returns (uint256 t);

Parameters

NameTypeDescription
priceuint256Current EUR/USD oracle price (18 decimals)

Returns

NameTypeDescription
tuint256Total effective collateral in USDC (6 decimals)

hasActiveHedger

Checks if there is an active hedger with an active position

Returns true if the single hedger has an active position

Notes:

  • security: View-only helper - no state changes

  • validation: None

  • state-changes: None - view function

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query

  • oracle: Not applicable

function hasActiveHedger() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if hedger has an active position, false otherwise

configureRiskAndFees

Configures risk and fee parameters in a single governance transaction.

Applies a full snapshot update for risk bounds, fee rates, and reserve split configuration.

Notes:

  • security: Restricted to governance; validates all bounds before state updates.

  • validation: Enforces leverage/fee/rate limits and reward split cap.

  • state-changes: Updates coreParams, minPositionHoldBlocks, minMarginAmount, and rewardFeeSplit.

  • events: No dedicated event emitted.

  • errors: Reverts on invalid role or any out-of-range config value.

  • reentrancy: Not applicable - no external calls.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle interaction.

function configureRiskAndFees(HedgerRiskConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgHedgerRiskConfigStruct containing risk and fee values to apply.

configureDependencies

Configures dependency addresses in a single governance transaction.

Changing feeCollector requires both governance and default-admin authority.

Notes:

  • security: Restricted to governance; extra admin gate for fee collector changes.

  • validation: Validates all dependency addresses are non-zero.

  • state-changes: Updates treasury, vault, oracle, yieldShift, and feeCollector.

  • events: No dedicated event emitted.

  • errors: Reverts on invalid role, unauthorized fee collector change, or zero addresses.

  • reentrancy: Not applicable - no external calls.

  • access: Restricted to GOVERNANCE_ROLE (plus DEFAULT_ADMIN_ROLE for fee collector change).

  • oracle: Updates the oracle dependency address.

function configureDependencies(HedgerDependencyConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgHedgerDependencyConfigStruct containing dependency addresses to apply.

emergencyClosePosition

Emergency closure of a hedge position by governance

Emergency closure process:

  1. Validates emergency role and position ownership
  2. Validates position is active
  3. Updates hedger stats and removes position
  4. Withdraws USDC from vault for hedger's margin

Security features:

  1. Role-based access control (EMERGENCY_ROLE)
  2. Position ownership validation

WARNING: unlike the normal exitHedgePosition flow, this deliberately does NOT run _validatePositionClosureSafety. If invoked while QEURO is outstanding (vault.totalMinted() > 0) it withdraws the hedger's full margin and can leave QEURO under-collateralized, pushing redemptions into liquidation mode. This is an accepted emergency escape hatch; the EmergencyPositionClosed event carries outstandingQeuro so operators can detect and react when backing has been removed under an active supply.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates emergency role, position ownership, active status

  • state-changes: Closes position, updates hedger stats, withdraws USDC from vault

  • events: Emits EmergencyPositionClosed with margin withdrawn and outstanding QEURO

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Not applicable

function emergencyClosePosition(address hedger, uint256 positionId) external nonReentrant;

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger whose position to close
positionIduint256Unique identifier of the position to close

pause

Pauses all contract operations in case of emergency

Emergency function to halt all user interactions

Notes:

  • security: Requires EMERGENCY_ROLE

  • validation: None required

  • state-changes: Sets contract to paused state

  • events: Emits Paused event

  • errors: Throws InvalidRole if caller lacks EMERGENCY_ROLE

  • reentrancy: Not applicable

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Not applicable

function pause() external;

unpause

Unpauses all contract operations after emergency pause

Emergency function to resume all user interactions

Notes:

  • security: Requires EMERGENCY_ROLE

  • validation: None required

  • state-changes: Sets contract to unpaused state

  • events: Emits Unpaused event

  • errors: Throws InvalidRole if caller lacks EMERGENCY_ROLE

  • reentrancy: Not applicable

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Not applicable

function unpause() external;

recover

Recovers tokens (token != 0) or ETH (token == 0) to treasury

Emergency function to recover accidentally sent tokens or ETH

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE

  • validation: Validates treasury address is set

  • state-changes: Transfers tokens/ETH to treasury

  • events: None

  • errors: Throws InvalidRole if caller lacks DEFAULT_ADMIN_ROLE

  • reentrancy: Protected by AdminFunctionsLibrary

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: Not applicable

function recover(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressAddress of token to recover (address(0) for ETH)
amountuint256Amount of tokens to recover (0 for all ETH)

setSingleHedger

Sets the single hedger address allowed to open positions

Single-hedger model. Bootstraps the hedger when none is set yet, otherwise performs a synchronous reassignment that is only permitted while the fixed positionId 1 is inactive (no live backing position). The legacy delayed multi-hedger rotation path has been retired (see applySingleHedgerRotation, now disabled); reassigning while a position is active would let a new hedger overwrite live exposure, so it reverts.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates governance role, non-zero hedger, and inactive position on reassign

  • state-changes: Updates singleHedger address

  • events: Emits SingleHedgerRotationApplied

  • errors: Reverts with InvalidAddress on zero hedger, HedgerHasActivePosition if reassigning while position 1 is active

  • reentrancy: Not protected - governance function

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function setSingleHedger(address hedger) external;

Parameters

NameTypeDescription
hedgeraddressAddress of the single hedger

correctLegacyMargin

Credits the verified July 2026 legacy residue to the existing Safe position once.

Fixed Base pool, beneficiary, opening block and 388448 micro-USDC; no token movement.

Notes:

  • security: Linked helper requires governance and a paused pool, and records replay protection.

  • validation: Requires initialized accounting, matching totals and the exact unallocated backing.

  • state-changes: Increases position/global margin and nominal exposure only.

  • events: LegacyMarginCorrected.

  • errors: Reverts on unauthorized, repeated or mismatched correction.

  • reentrancy: Protected by nonReentrant; external reads are static.

  • access: Governance only, enforced by the linked helper.

  • oracle: No price dependency; original-cost accounting is used.

function correctLegacyMargin() external nonReentrant;

manageHedgerMigration

Manages a consensual transfer of the live hedge position to a contract wallet.

Current owner proposes, recipient accepts, governance executes while paused.

Notes:

  • security: Three-party authorization, expiry and proposal nonce prevent unilateral transfers/replay.

  • validation: Requires active remaining-cost accounting and a clean receiving hedger account.

  • state-changes: Moves owner mappings and pool reward state; preserves all position economics.

  • events: HedgerMigrationProposed, HedgerMigrationAccepted, HedgerMigrationCancelled, HedgerMigrationExecuted, SingleHedgerRotationApplied.

  • errors: MigrationUnauthorized, InvalidMigration, MigrationExpired, MigrationNotAccepted, RecipientHasHedgerState, MigrationRequiresPause.

  • reentrancy: Protected by nonReentrant; migration performs no external token calls.

  • access: Current hedger, proposed recipient, or governance according to the action.

  • oracle: No oracle dependency; no position revaluation.

function manageHedgerMigration(HedgerPoolMigrationLibrary.Request calldata request) external nonReentrant;

Parameters

NameTypeDescription
requestHedgerPoolMigrationLibrary.RequestAction and exact proposal fields; proposalId is zero only for Propose.

hedgerMigration

Reads the currently proposed hedge ownership transfer.

Proposal data resides in a dedicated hashed storage namespace.

Notes:

  • security: Read-only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: No state changes.

  • access: Public.

  • oracle: None.

function hedgerMigration() external view returns (HedgerPoolMigrationLibrary.Proposal memory);

Returns

NameTypeDescription
<none>HedgerPoolMigrationLibrary.ProposalCurrent proposal; zero fields indicate no pending transfer.

fundRewardReserve

Deposit USDC into the reward reserve so hedging rewards can be paid out.

Permissionless funding path; caller must approve USDC before calling.

Notes:

  • security: Uses nonReentrant protection and pulls tokens from caller.

  • validation: Reverts when amount is zero.

  • state-changes: Transfers USDC into HedgerPool reward reserves.

  • events: Emits RewardReserveFunded.

  • errors: Reverts on zero amount or failed token transfer.

  • reentrancy: Protected by nonReentrant.

  • access: Public.

  • oracle: No oracle interaction.

function fundRewardReserve(uint256 amount) external nonReentrant;

Parameters

NameTypeDescription
amountuint256Amount of USDC to deposit (6 decimals).

_getValidOraclePrice

Gets a valid EUR/USD price from the oracle

Internal function to fetch and validate oracle price

Notes:

  • security: Validates oracle price is valid

  • validation: Validates oracle price is valid

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws InvalidOraclePrice if price is invalid

  • reentrancy: Not protected - internal function

  • access: Internal function - no access restrictions

  • oracle: Requires fresh oracle price data

function _getValidOraclePrice() internal returns (uint256);

Returns

NameTypeDescription
<none>uint256price Valid EUR/USD price from oracle

_validateRole

Validates that the caller has the required role

Internal function to check role-based access control

Notes:

  • security: Validates caller has the specified role

  • validation: Checks role against AccessControlLibrary

  • state-changes: None (view function)

  • events: None

  • errors: Throws InvalidRole if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function

  • oracle: Not applicable

function _validateRole(bytes32 role) internal view;

Parameters

NameTypeDescription
rolebytes32The role to validate against

_finalizePosition

Removes a position from the hedger's position arrays

Finalizes position closure by updating hedger and protocol totals

Internal function to maintain position tracking arrays

Internal helper to clean up position state and update aggregate statistics

Notes:

  • security: Validates position exists before removal

  • validation: Ensures position exists in hedger's array

  • state-changes: Removes position from arrays and updates indices

  • events: None

  • errors: Throws PositionNotFound if position doesn't exist

  • reentrancy: Not applicable - internal function

  • access: Internal function

  • oracle: Not applicable

  • security: Internal function - assumes all validations done by caller

  • validation: Assumes marginDelta and exposureDelta are valid and don't exceed current totals

  • state-changes: Decrements hedger margin/exposure, protocol totals, marks position inactive, updates hedger position tracking

  • events: None - events emitted by caller

  • errors: None - assumes valid inputs from caller

  • reentrancy: Not applicable - internal function, no external calls

  • access: Internal - only callable within contract

  • oracle: Not applicable

function _finalizePosition(
    address hedger,
    uint256 positionId,
    HedgePosition storage position,
    uint256 marginDelta,
    uint256 exposureDelta
) internal;

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger whose position to remove
positionIduint256ID of the position to remove
positionHedgePositionStorage reference to the position being finalized
marginDeltauint256Amount of margin being removed from the position
exposureDeltauint256Amount of exposure being removed from the position

_unwindFilledVolume

Unwinds filled volume from a position

Clears position's filled volume (no redistribution needed with single position)

Notes:

  • security: Internal function - assumes position is valid and active

  • validation: Validates totalFilledExposure >= cachedFilledVolume before decrementing

  • state-changes: Clears position filledVolume, decrements totalFilledExposure

  • events: No events emitted

  • errors: Reverts with InsufficientHedgerCapacity if totalFilledExposure < cachedFilledVolume

  • reentrancy: Protected by nonReentrant on all public entry points

  • access: Internal - only callable within contract

  • oracle: Not applicable

function _unwindFilledVolume(HedgePosition storage position) internal;

Parameters

NameTypeDescription
positionHedgePositionStorage reference to the position being unwound

_increaseFilledVolume

Allocates user mint exposure to the hedger position

Allocates usdcAmount to the single hedger position if healthy

Notes:

  • security: Caller must ensure hedger position exists

  • validation: Validates liquidity availability and capacity before allocation

  • state-changes: Updates filledVolume and totalFilledExposure

  • events: None

  • errors: Reverts if capacity is insufficient or liquidity is absent

  • reentrancy: Not applicable - internal function

  • access: Internal helper

  • oracle: Requires current oracle price to check position health

function _increaseFilledVolume(uint256 usdcAmount, uint256 currentPrice, uint256 qeuroAmount) internal;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC exposure to allocate (6 decimals)
currentPriceuint256Current EUR/USD oracle price supplied by the caller (18 decimals)
qeuroAmountuint256QEURO amount that was minted (18 decimals)

_decreaseFilledVolume

Releases exposure from the hedger position following a user redeem

Decreases fills from the single hedger position

Notes:

  • security: Internal function - validates price and amounts

  • validation: Validates usdcAmount > 0, redeemPrice > 0, and sufficient filled exposure

  • state-changes: Decreases filledVolume, updates totalFilledExposure, calculates realized P&L

  • events: Emits MarginUpdated when realized P&L changes margin

  • errors: Reverts with InvalidOraclePrice, NoActiveHedgerLiquidity, or InsufficientHedgerCapacity

  • reentrancy: Not applicable - internal function

  • access: Internal helper only

  • oracle: Uses provided redeemPrice parameter

function _decreaseFilledVolume(uint256 usdcAmount, uint256 redeemPrice, uint256 qeuroAmount) internal;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to release (at redeem price) (6 decimals)
redeemPriceuint256Current EUR/USD oracle price (18 decimals) for P&L calculation
qeuroAmountuint256QEURO amount that was redeemed (18 decimals)

_applyFillChange

Applies a fill delta to a single position

Handles both increases and decreases while enforcing capacity constraints

Notes:

  • security: Caller must ensure the storage reference is valid

  • validation: Validates capacity or availability before applying the delta

  • state-changes: Updates the position’s filledVolume

  • events: None

  • errors: Reverts with InsufficientHedgerCapacity on invalid operations

  • reentrancy: Not applicable - internal function

  • access: Internal helper

  • oracle: Not applicable

function _applyFillChange(HedgePosition storage position, uint256 delta, bool increase) internal;

Parameters

NameTypeDescription
positionHedgePositionStorage pointer to the position struct
deltauint256Amount of fill change to apply
increaseboolTrue to increase fill, false to decrease

_updateEntryPriceAfterFill

Updates weighted-average entry price after new fills

Calculates new weighted average entry price when position receives new fills

Notes:

  • security: Internal function - validates price is valid

  • validation: Validates price > 0 and price <= type(uint96).max

  • state-changes: Updates pos.entryPrice with weighted average

  • events: None

  • errors: Throws InvalidOraclePrice if price is invalid

  • reentrancy: Not applicable - internal function

  • access: Internal helper only

  • oracle: Uses provided price parameter

function _updateEntryPriceAfterFill(HedgePosition storage pos, uint256 prevFilled, uint256 delta, uint256 price)
    internal;

Parameters

NameTypeDescription
posHedgePositionStorage pointer to the position struct
prevFilleduint256Previous filled volume before the new fill
deltauint256Amount of new fill being added
priceuint256Current EUR/USD oracle price for the new fill (18 decimals)

_processRedeem

Realizes the redeemed QEURO's P&L and releases its original cost.

The realized delta is proportional remaining cost minus the redeemed amount's current USDC value. Historical realized P&L is informational only.

Notes:

  • security: Records each redeemed portion's profit or loss exactly once.

  • validation: Caller bounds qeuroAmount to the position's current backing.

  • state-changes: Updates margin, realized history, position size and remaining cost.

  • events: None.

  • errors: InvalidAmount if realized P&L exceeds the packed signed range.

  • reentrancy: No external untrusted calls.

  • access: Internal.

  • oracle: Uses the caller's validated price.

function _processRedeem(
    uint256 posId,
    HedgePosition storage pos,
    uint256 share,
    uint256 filledBefore,
    uint256 price,
    uint256 qeuroAmount
) internal;

Parameters

NameTypeDescription
posIduint256Position identifier.
posHedgePositionPosition storage reference.
shareuint256Original USDC cost released by this redemption.
filledBeforeuint256Original USDC cost of the remaining position before redemption.
priceuint256Validated EUR/USD price, 18 decimals.
qeuroAmountuint256Redeemed QEURO, 18 decimals.

_applyRealizedPnLToMargin

Applies realized P&L to position margin and emits MarginUpdated

Handles both profit and loss branches in a single path to keep bytecode compact.

Notes:

  • security: Internal accounting helper called after redemption validations.

  • validation: Handles zero delta and relies on library-validated transition bounds.

  • state-changes: Updates totalMargin, pos.margin, and pos.positionSize.

  • events: Emits MarginUpdated when realizedDelta != 0.

  • errors: Reverts only through downstream arithmetic/library checks.

  • reentrancy: Not applicable - internal function with no external calls.

  • access: Internal helper only.

  • oracle: No oracle interaction.

function _applyRealizedPnLToMargin(uint256, HedgePosition storage pos, int256 realizedDelta) internal;

Parameters

NameTypeDescription
<none>uint256
posHedgePositionPosition storage reference
realizedDeltaint256Realized P&L amount (positive = profit, negative = loss)

_checkpointRewards

Checkpoints the configured hedger's interest reward before exposure changes.

No-op when no hedger is configured.

Notes:

  • security: Uses the linked accounting library and existing reward storage.

  • validation: Applies the configured reward-period cap and overflow guard.

  • state-changes: Updates pending rewards and the hedger's accrual timestamp.

  • events: None.

  • errors: RewardOverflow when pending accounting exceeds uint128.

  • reentrancy: No external calls.

  • access: Internal.

  • oracle: No oracle dependency.

function _checkpointRewards() private;

Events

LegacyMarginCorrected

event LegacyMarginCorrected(bytes32 indexed correctionId, address indexed hedger, uint256 amount);

HedgePositionOpened

event HedgePositionOpened(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

HedgePositionClosed

event HedgePositionClosed(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

MarginUpdated

event MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

ETHRecovered

event ETHRecovered(address indexed to, uint256 indexed amount);

RewardReserveFunded

Emitted when USDC is deposited into the reward reserve

event RewardReserveFunded(address indexed funder, uint256 amount);

HedgerMigrationProposed

event HedgerMigrationProposed(
    bytes32 indexed proposalId, address indexed previousHedger, address indexed newHedger, uint64 expiresAt
);

HedgerMigrationAccepted

event HedgerMigrationAccepted(bytes32 indexed proposalId);

HedgerMigrationCancelled

event HedgerMigrationCancelled(bytes32 indexed proposalId);

HedgerMigrationExecuted

event HedgerMigrationExecuted(
    bytes32 indexed proposalId, address indexed previousHedger, address indexed newHedger
);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

EmergencyPositionClosed

Emitted when EMERGENCY_ROLE force-closes a position.

When outstandingQeuro is non-zero the closure withdraws hedger margin while QEURO is still outstanding, which reduces protocol collateralization and may push redemptions into liquidation mode. This is an intentional emergency escape hatch; the event exists so monitoring/alerting can detect when backing has been removed under an active supply.

event EmergencyPositionClosed(
    address indexed hedger, uint256 indexed positionId, uint256 marginWithdrawn, uint256 outstandingQeuro
);

Parameters

NameTypeDescription
hedgeraddressHedger whose position was force-closed
positionIduint256Closed position id
marginWithdrawnuint256Margin (USDC, 6 decimals) returned to the hedger from the vault
outstandingQeurouint256QEURO still outstanding at closure time (18 decimals); non-zero means under-backed

Errors

PositionClosureRestricted

error PositionClosureRestricted();

LegacyCorrectionUnauthorized

error LegacyCorrectionUnauthorized();

LegacyCorrectionStateMismatch

error LegacyCorrectionStateMismatch();

LegacyCorrectionAlreadyApplied

error LegacyCorrectionAlreadyApplied();

ConfigValueTooHigh

error ConfigValueTooHigh();

ConfigValueTooLow

error ConfigValueTooLow();

FeeTooHigh

error FeeTooHigh();

InsufficientBalance

error InsufficientBalance();

YieldClaimFailed

error YieldClaimFailed();

Structs

CoreParams

struct CoreParams {
    uint64 minMarginRatio;
    uint16 maxLeverage;
    uint16 entryFee;
    uint16 exitFee;
    uint16 marginFee;
    uint16 eurInterestRate;
    uint16 usdInterestRate;
    uint8 reserved;
}

HedgerRiskConfig

struct HedgerRiskConfig {
    uint256 minMarginRatio;
    uint256 maxLeverage;
    uint256 minPositionHoldBlocks;
    uint256 minMarginAmount;
    uint256 eurInterestRate;
    uint256 usdInterestRate;
    uint256 entryFee;
    uint256 exitFee;
    uint256 marginFee;
    uint256 rewardFeeSplit;
}

HedgerDependencyConfig

struct HedgerDependencyConfig {
    address treasury;
    address vault;
    address oracle;
    address yieldShift;
    address feeCollector;
}

HedgePosition

struct HedgePosition {
    address hedger;
    uint96 positionSize;
    uint96 filledVolume; // Remaining original USDC cost of qeuroBacked
    uint96 margin;
    uint96 entryPrice;
    uint32 entryTime;
    uint32 lastUpdateTime;
    int128 unrealizedPnL;
    int128 realizedPnL; // Informational history; already reflected in margin
    uint16 leverage;
    bool isActive;
    uint128 qeuroBacked; // Exact QEURO amount backed by this position (18 decimals)
    uint64 openBlock; // Block number when position was opened (for min hold period)
}

HedgerRewardState

struct HedgerRewardState {
    uint128 pendingRewards;
    uint64 lastRewardClaim;
}

QEUROToken

Git Source

Inherits: Initializable, ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IVersioned

Title: QEUROToken

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Euro-pegged stablecoin token for the Quantillon protocol

Main characteristics:

  • Standard ERC20 with 18 decimals
  • Mint/Burn controlled only by the vault
  • Emergency pause in case of issues
  • Upgradeable via UUPS pattern
  • Dynamic supply cap for governance flexibility
  • Blacklist/whitelist functionality for compliance
  • Rate limiting for mint/burn operations
  • Decimal precision handling for external price feeds

Security features:

  • Role-based access control for all critical operations
  • Emergency pause mechanism for crisis situations
  • Rate limiting to prevent abuse
  • Blacklist/whitelist for regulatory compliance
  • Upgradeable architecture for future improvements

Tokenomics:

  • Initial supply: 0 (all tokens minted through vault operations)
  • Maximum supply: Configurable by governance (default 100M QEURO)
  • Decimals: 18 (standard for ERC20 tokens)
  • Peg: 1:1 with Euro (managed by vault operations)

Note: security-contact: team@quantillon.money

Constants

MINTER_ROLE

Role for minting tokens (assigned to QuantillonVault only)

keccak256 hash avoids role collisions with other contracts

Only the vault should have this role to maintain tokenomics

bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE")

BURNER_ROLE

Role for burning tokens (assigned to QuantillonVault only)

keccak256 hash avoids role collisions with other contracts

Only the vault should have this role to maintain tokenomics

bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE")

PAUSER_ROLE

Role for pausing the contract in emergency situations

keccak256 hash avoids role collisions with other contracts

Should be assigned to governance or emergency multisig

bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE")

COMPLIANCE_ROLE

Role for managing blacklist/whitelist for compliance

keccak256 hash avoids role collisions with other contracts

Should be assigned to compliance team or governance

bytes32 public constant COMPLIANCE_ROLE = keccak256("COMPLIANCE_ROLE")

DEFAULT_MAX_SUPPLY

Default maximum supply limit (100 million QEURO)

Can be updated by governance through updateMaxSupply()

Value: 100,000,000 * 10^18 = 100,000,000 QEURO

uint256 public constant DEFAULT_MAX_SUPPLY = 100_000_000 * 1e18

MAX_RATE_LIMIT

Maximum rate limit for mint/burn operations (per reset period)

Prevents abuse and provides time for emergency response

Value: 10,000,000 * 10^18 = 10,000,000 QEURO per reset period (~300 blocks)

uint256 public constant MAX_RATE_LIMIT = 10_000_000 * 1e18

RATE_LIMIT_RESET_PERIOD

Rate limit reset period in blocks (~1 hour assuming 12 second blocks)

Using block numbers instead of timestamps for security against miner manipulation

uint256 public constant RATE_LIMIT_RESET_PERIOD = 300

PRECISION

Precision for decimal calculations (18 decimals)

Standard precision used throughout the protocol

Value: 10^18

uint256 public constant PRECISION = 1e18

MAX_BATCH_SIZE

Maximum batch size for mint operations to prevent DoS

Prevents out-of-gas attacks through large arrays

uint256 public constant MAX_BATCH_SIZE = 100

MAX_COMPLIANCE_BATCH_SIZE

Maximum batch size for compliance operations to prevent DoS

Prevents out-of-gas attacks through large blacklist/whitelist arrays

uint256 public constant MAX_COMPLIANCE_BATCH_SIZE = 50

State Variables

maxSupply

Current maximum supply limit (updatable by governance)

Initialized to DEFAULT_MAX_SUPPLY, can be changed by governance

Prevents infinite minting and maintains tokenomics

uint256 public maxSupply

rateLimitCaps

RateLimitCaps public rateLimitCaps

rateLimitInfo

RateLimitInfo public rateLimitInfo

mintingKillswitch

Emergency killswitch to prevent all QEURO minting operations

When enabled (true), blocks both regular and batch minting functions

Can only be toggled by addresses with PAUSER_ROLE

Used as a crisis management tool when protocol lacks sufficient collateral

Independent of the general pause mechanism - provides granular control

bool public mintingKillswitch

isBlacklisted

Blacklist mapping for compliance and security

Blacklisted addresses cannot transfer or receive tokens

Can be managed by addresses with COMPLIANCE_ROLE

mapping(address => bool) public isBlacklisted

isWhitelisted

Whitelist mapping for compliance (if enabled)

When whitelistEnabled is true, only whitelisted addresses can transfer

Can be managed by addresses with COMPLIANCE_ROLE

mapping(address => bool) public isWhitelisted

whitelistEnabled

Whether whitelist mode is enabled

When true, only whitelisted addresses can transfer tokens

Can be toggled by addresses with COMPLIANCE_ROLE

bool public whitelistEnabled

minPricePrecision

Minimum precision for external price feeds

Used to validate price feed precision for accurate calculations

Can be updated by governance through updateMinPricePrecision()

uint256 public minPricePrecision

treasury

Treasury address for ETH recovery

SECURITY: Only this address can receive ETH from recoverETH function

address public treasury

feeCollector

FeeCollector contract address for protocol fee collection

Protocol fees from minting are sent to this contract

address public feeCollector

_flashLoanBalanceBefore

Balance before flash loan check (used by flashLoanProtection modifier)

uint256 private _flashLoanBalanceBefore

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

flashLoanProtection

Modifier to protect against flash loan attacks

Uses the FlashLoanProtectionLibrary to check QEURO balance consistency

modifier flashLoanProtection() ;

_flashLoanProtectionBefore

function _flashLoanProtectionBefore() private;

_flashLoanProtectionAfter

function _flashLoanProtectionAfter() private view;

constructor

Constructor for QEURO token contract

Disables initializers for security

Notes:

  • security: Disables initializers for security

  • validation: No validation needed

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the QEURO token (called only once at deployment)

This function replaces the constructor. It:

  1. Initializes the ERC20 token with name and symbol
  2. Configures the role system
  3. Assigns appropriate roles
  4. Configures pause and upgrade system
  5. Sets initial rate limits and precision settings
  6. Sets FeeCollector address for protocol fees

Security considerations:

  • Only callable once (initializer modifier)
  • Validates input parameters
  • Sets up proper role hierarchy
  • Initializes all state variables

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Initializes all contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin, address vault, address _timelock, address _treasury, address _feeCollector)
    public
    initializer;

Parameters

NameTypeDescription
adminaddressAddress that will have the DEFAULT_ADMIN_ROLE
vaultaddressAddress of the QuantillonVault (will get MINTER_ROLE and BURNER_ROLE)
_timelockaddressAddress of the timelock contract
_treasuryaddressTreasury address for protocol fees
_feeCollectoraddressAddress of the FeeCollector contract for protocol fee collection

mint

Mints QEURO tokens to a specified address

Implemented securities:

  • Only the vault can call this function (MINTER_ROLE)
  • The contract must not be paused
  • Respect for maximum supply cap
  • Input parameter validation
  • Rate limiting
  • Blacklist/whitelist checks
  • Protocol fee collection (0.1% of minted amount)

Protocol fee: 0.1% of the minted amount is collected and sent to FeeCollector The user receives (amount - fee), and FeeCollector receives the fee Usage example: vault.mint(user, 1000 * 1e18) for 1000 QEURO

  • User receives: 999 QEURO (1000 - 1)
  • FeeCollector receives: 1 QEURO (0.1% fee)

Security considerations:

  • Only MINTER_ROLE can mint
  • Pause check
  • Rate limiting
  • Blacklist/whitelist checks
  • Supply cap verification
  • Secure minting using OpenZeppelin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to MINTER_ROLE

  • oracle: No oracle dependencies

function mint(address to, uint256 amount)
    external
    onlyRole(MINTER_ROLE) // Only the vault can mint
    whenNotPaused;

Parameters

NameTypeDescription
toaddressAddress that will receive the tokens
amountuint256Amount of tokens to mint (in wei, 18 decimals)

batchMint

Batch mint QEURO tokens to multiple addresses

Applies the same validations as single mint per item to avoid bypassing rate limits, blacklist/whitelist checks, and max supply constraints. Protocol fee (0.1%) is collected for each mint in the batch.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to MINTER_ROLE

  • oracle: No oracle dependencies

function batchMint(address[] calldata recipients, uint256[] calldata amounts)
    external
    onlyRole(MINTER_ROLE)
    whenNotPaused
    flashLoanProtection;

Parameters

NameTypeDescription
recipientsaddress[]Array of recipient addresses
amountsuint256[]Array of amounts to mint (18 decimals)

burn

Burns QEURO tokens from a specified address

Implemented securities:

  • Only the vault can call this function (BURNER_ROLE)
  • The contract must not be paused
  • Sufficient balance verification
  • Parameter validation
  • Rate limiting Note: The vault must have an allowance or be authorized otherwise

Security considerations:

  • Only BURNER_ROLE can burn
  • Pause check
  • Rate limiting
  • Secure burning using OpenZeppelin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to BURNER_ROLE

  • oracle: No oracle dependencies

  • security: No flash loan protection needed - only vault can burn

function burn(address from, uint256 amount)
    external
    onlyRole(BURNER_ROLE) // Only the vault can burn
    whenNotPaused;

Parameters

NameTypeDescription
fromaddressAddress from which to burn tokens
amountuint256Amount of tokens to burn

batchBurn

Batch burn QEURO tokens from multiple addresses

Applies the same validations as single burn per item to avoid bypassing rate limits and balance checks. Accumulates total for rate limiting.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to BURNER_ROLE

  • oracle: No oracle dependencies

function batchBurn(address[] calldata froms, uint256[] calldata amounts)
    external
    onlyRole(BURNER_ROLE)
    whenNotPaused
    flashLoanProtection;

Parameters

NameTypeDescription
fromsaddress[]Array of addresses to burn from
amountsuint256[]Array of amounts to burn (18 decimals)

_checkAndUpdateMintRateLimit

Checks and updates the mint rate limit for the caller

Implements sliding window rate limiting using block numbers to prevent abuse

Notes:

  • security: Resets rate limit if reset period has passed (~300 blocks), prevents block manipulation

  • validation: Validates amount against current rate limit caps

  • state-changes: Updates rateLimitInfo.currentHourMinted and lastRateLimitReset

  • events: No events emitted

  • errors: Throws RateLimitExceeded if amount would exceed current rate limit

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _checkAndUpdateMintRateLimit(uint256 amount) internal;

Parameters

NameTypeDescription
amountuint256The amount to be minted (18 decimals), used to check against rate limits

updateRateLimits

Updates rate limits for mint and burn operations

Only callable by admin

Security considerations:

  • Validates new limits
  • Ensures new limits are not zero
  • Ensures new limits are not too high
  • Updates rateLimitCaps (mint and burn) in a single storage slot
  • Emits RateLimitsUpdated event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateRateLimits(uint256 newMintLimit, uint256 newBurnLimit) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newMintLimituint256New mint rate limit per reset period (~300 blocks)
newBurnLimituint256New burn rate limit per reset period (~300 blocks)

blacklistAddress

Blacklists an address

Only callable by compliance role

Security considerations:

  • Validates input parameters
  • Prevents blacklisting of zero address
  • Prevents blacklisting of already blacklisted addresses
  • Updates isBlacklisted mapping
  • Emits AddressBlacklisted event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function blacklistAddress(address account, string memory reason) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountaddressAddress to blacklist
reasonstringReason for blacklisting

unblacklistAddress

Removes an address from blacklist

Only callable by compliance role

Security considerations:

  • Validates input parameter
  • Prevents unblacklisting of non-blacklisted addresses
  • Updates isBlacklisted mapping
  • Emits AddressUnblacklisted event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function unblacklistAddress(address account) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountaddressAddress to remove from blacklist

whitelistAddress

Whitelists an address

Only callable by compliance role

Security considerations:

  • Validates input parameters
  • Prevents whitelisting of zero address
  • Prevents whitelisting of already whitelisted addresses
  • Updates isWhitelisted mapping
  • Emits AddressWhitelisted event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function whitelistAddress(address account) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountaddressAddress to whitelist

unwhitelistAddress

Removes an address from whitelist

Only callable by compliance role

Security considerations:

  • Validates input parameter
  • Prevents unwhitelisting of non-whitelisted addresses
  • Updates isWhitelisted mapping
  • Emits AddressUnwhitelisted event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function unwhitelistAddress(address account) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountaddressAddress to remove from whitelist

toggleWhitelistMode

Toggles whitelist mode

Only callable by compliance role

Security considerations:

  • Validates input parameter
  • Updates whitelistEnabled state
  • Emits WhitelistModeToggled event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function toggleWhitelistMode(bool enabled) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
enabledboolWhether to enable whitelist mode

batchBlacklistAddresses

Batch blacklist multiple addresses

Only callable by compliance role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function batchBlacklistAddresses(address[] calldata accounts, string[] calldata reasons)
    external
    onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to blacklist
reasonsstring[]Array of reasons for blacklisting

batchUnblacklistAddresses

Batch unblacklist multiple addresses

Only callable by compliance role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function batchUnblacklistAddresses(address[] calldata accounts) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to remove from blacklist

batchWhitelistAddresses

Batch whitelist multiple addresses

Only callable by compliance role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function batchWhitelistAddresses(address[] calldata accounts) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to whitelist

batchUnwhitelistAddresses

Batch unwhitelist multiple addresses

Only callable by compliance role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to COMPLIANCE_ROLE

  • oracle: No oracle dependencies

function batchUnwhitelistAddresses(address[] calldata accounts) external onlyRole(COMPLIANCE_ROLE);

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to remove from whitelist

updateMinPricePrecision

Updates minimum price precision for external feeds

Only callable by admin

Security considerations:

  • Validates input parameter
  • Prevents setting precision to zero
  • Prevents setting precision higher than PRECISION
  • Updates minPricePrecision
  • Emits MinPricePrecisionUpdated event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateMinPricePrecision(uint256 newPrecision) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newPrecisionuint256New minimum precision (e.g., 1e6 for 6 decimals)

normalizePrice

Normalizes a price value to 18 decimals

Helper function for external integrations

Security considerations:

  • Validates input parameters
  • Prevents too many decimals
  • Prevents zero price
  • Handles normalization correctly

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function normalizePrice(uint256 price, uint8 feedDecimals) external pure returns (uint256);

Parameters

NameTypeDescription
priceuint256Price value from external feed
feedDecimalsuint8Number of decimals in the price feed

Returns

NameTypeDescription
<none>uint256Normalized price with 18 decimals

validatePricePrecision

Validates price precision from external feed

Helper function for external integrations

Security considerations:

  • Validates input parameters
  • Handles normalization if feedDecimals is not 18
  • Returns true if price is above or equal to minPricePrecision

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function validatePricePrecision(uint256 price, uint8 feedDecimals) external view returns (bool);

Parameters

NameTypeDescription
priceuint256Price value from external feed
feedDecimalsuint8Number of decimals in the price feed

Returns

NameTypeDescription
<none>boolWhether the price meets minimum precision requirements

pause

Pauses all token operations (emergency only)

When paused:

  • No transfers possible
  • No mint/burn possible
  • Only read functions work Used in case of:
  • Critical bug discovered
  • Ongoing attack
  • Emergency protocol maintenance

Security considerations:

  • Only PAUSER_ROLE can pause
  • Pauses all token operations
  • Prevents any state changes

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to PAUSER_ROLE

  • oracle: No oracle dependencies

function pause() external onlyRole(PAUSER_ROLE);

unpause

Removes pause and restores normal operations

Can only be called by a PAUSER_ROLE Used after resolving the issue that caused the pause

Security considerations:

  • Only PAUSER_ROLE can unpause
  • Unpauses all token operations
  • Allows normal state changes

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to PAUSER_ROLE

  • oracle: No oracle dependencies

function unpause() external onlyRole(PAUSER_ROLE);

decimals

Returns the number of decimals for the token (always 18)

Always returns 18 for DeFi compatibility

Security considerations:

  • Always returns 18
  • No input validation
  • No state changes

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function decimals() public pure override returns (uint8);

Returns

NameTypeDescription
<none>uint8Number of decimals (18 for DeFi compatibility)

isMinter

Checks if an address has the minter role

Checks if account has MINTER_ROLE

Security considerations:

  • Checks if account has MINTER_ROLE
  • No input validation
  • No state changes

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function isMinter(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>booltrue if the address can mint

isBurner

Checks if an address has the burner role

Checks if account has BURNER_ROLE

Security considerations:

  • Checks if account has BURNER_ROLE
  • No input validation
  • No state changes

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function isBurner(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>booltrue if the address can burn

getSupplyUtilization

Calculates the percentage of maximum supply utilization

Useful for monitoring:

  • 0 = 0% used
  • 5000 = 50% used
  • 10000 = 100% used (maximum supply reached)

Security considerations:

  • Calculates percentage based on totalSupply and maxSupply
  • Handles division by zero
  • Returns 0 if totalSupply is 0

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getSupplyUtilization() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Percentage in basis points (0-10000, where 10000 = 100%)

batchTransfer

Batch transfer QEURO tokens to multiple addresses

Performs multiple transfers from msg.sender to recipients. Uses OpenZeppelin's transfer mechanism with compliance checks.

Notes:

  • security: Validates all recipients and amounts, enforces blacklist/whitelist checks

  • validation: Validates array lengths match, amounts > 0, recipients != address(0)

  • state-changes: Updates balances for all recipients and sender

  • events: Emits Transfer events for each successful transfer

  • errors: Throws ArrayLengthMismatch, BatchSizeTooLarge, InvalidAddress, InvalidAmount, BlacklistedAddress, NotWhitelisted

  • reentrancy: Protected by whenNotPaused modifier

  • access: Public - requires sufficient balance and compliance checks

  • oracle: No oracle dependencies

function batchTransfer(address[] calldata recipients, uint256[] calldata amounts)
    external
    whenNotPaused
    returns (bool);

Parameters

NameTypeDescription
recipientsaddress[]Array of recipient addresses
amountsuint256[]Array of amounts to transfer (18 decimals)

Returns

NameTypeDescription
<none>boolsuccess Always returns true if all transfers succeed

_update

Hook called before each token transfer

Adds pause verification and blacklist checks to standard OpenZeppelin transfers

Security considerations:

  • Checks if transfer is from a blacklisted address
  • Checks if transfer is to a blacklisted address
  • If whitelist is enabled, checks if recipient is whitelisted
  • Prevents transfers if any checks fail
  • Calls super._update for standard ERC20 logic

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by whenNotPaused modifier

  • access: Internal function

  • oracle: No oracle dependencies

function _update(address from, address to, uint256 amount) internal override whenNotPaused;

Parameters

NameTypeDescription
fromaddressSource address (address(0) for mint)
toaddressDestination address (address(0) for burn)
amountuint256Amount transferred

recoverToken

Recover tokens accidentally sent to the contract to treasury only

Only DEFAULT_ADMIN_ROLE can recover tokens to treasury

Security considerations:

  • Only DEFAULT_ADMIN_ROLE can recover
  • Prevents recovery of own QEURO tokens
  • Tokens are sent to treasury address only
  • Uses SafeERC20 for secure transfers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

updateMaxSupply

Updates the maximum supply limit (governance only)

Function to adjust supply cap if necessary Requires governance and must be used with caution

IMPROVEMENT: Now functional with dynamic supply cap

Security considerations:

  • Only DEFAULT_ADMIN_ROLE can update
  • Validates newMaxSupply
  • Prevents setting cap below current supply
  • Prevents setting cap to zero
  • Emits SupplyCapUpdated event

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateMaxSupply(uint256 newMaxSupply) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newMaxSupplyuint256New supply limit

updateTreasury

Update treasury address

SECURITY: Only governance can update treasury address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

updateFeeCollector

Update FeeCollector address

SECURITY: Only governance can update FeeCollector address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateFeeCollector(address _feeCollector) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_feeCollectoraddressNew FeeCollector address

getTokenInfo

Complete token information (for monitoring)

Returns current state of the token for monitoring purposes

Security considerations:

  • Returns current state of the token
  • No input validation
  • No state changes

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getTokenInfo()
    external
    view
    returns (
        string memory name_,
        string memory symbol_,
        uint8 decimals_,
        uint256 totalSupply_,
        uint256 maxSupply_,
        bool isPaused_,
        bool whitelistEnabled_,
        uint256 mintRateLimit_,
        uint256 burnRateLimit_
    );

Returns

NameTypeDescription
name_stringToken name
symbol_stringToken symbol
decimals_uint8Number of decimals
totalSupply_uint256Current total supply
maxSupply_uint256Maximum authorized supply
isPaused_boolPause state
whitelistEnabled_boolWhether whitelist mode is enabled
mintRateLimit_uint256Current mint rate limit
burnRateLimit_uint256Current burn rate limit

mintRateLimit

Get current mint rate limit (per hour)

Returns current mint rate limit

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function mintRateLimit() external view returns (uint256 limit);

Returns

NameTypeDescription
limituint256Mint rate limit in wei per hour (18 decimals)

setMintingKillswitch

Toggle the emergency minting killswitch to enable/disable all minting operations

Emergency function that provides granular control over minting without affecting other operations

Can only be called by addresses with PAUSER_ROLE for security

Used as a crisis management tool when protocol lacks sufficient collateral

Independent of the general pause mechanism - allows selective operation blocking

When enabled, both mint() and batchMint() functions will revert with MintingDisabled error

Burning operations remain unaffected by the killswitch

Notes:

  • security: Only callable by PAUSER_ROLE holders

  • validation: Validates caller has PAUSER_ROLE

  • events: Emits MintingKillswitchToggled event with new state and caller

  • errors: Throws AccessControlUnauthorizedAccount if caller lacks PAUSER_ROLE

  • state-changes: Updates mintingKillswitch state variable

  • access: Restricted to PAUSER_ROLE

  • reentrancy: Not protected - simple state change

  • oracle: No oracle dependencies

function setMintingKillswitch(bool enabled) external onlyRole(PAUSER_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable killswitch (block all minting), false to disable (allow minting)

burnRateLimit

Get current burn rate limit (per hour)

Returns current burn rate limit

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function burnRateLimit() external view returns (uint256 limit);

Returns

NameTypeDescription
limituint256Burn rate limit in wei per hour (18 decimals)

Events

TokensMinted

Emitted when tokens are minted

OPTIMIZED: Indexed amount for efficient filtering by mint size

event TokensMinted(address indexed to, uint256 indexed amount, address indexed minter);

Parameters

NameTypeDescription
toaddressRecipient of the tokens
amountuint256Amount minted in wei (18 decimals)
minteraddressAddress that performed the mint (vault)

MintingKillswitchToggled

Emitted when the minting killswitch is toggled on or off

Provides transparency for emergency actions taken by protocol administrators

event MintingKillswitchToggled(bool enabled, address indexed caller);

Parameters

NameTypeDescription
enabledboolTrue if killswitch is being enabled (minting blocked), false if disabled (minting allowed)
calleraddressAddress of the PAUSER_ROLE holder who toggled the killswitch

TokensBurned

Emitted when tokens are burned

OPTIMIZED: Indexed amount for efficient filtering by burn size

event TokensBurned(address indexed from, uint256 indexed amount, address indexed burner);

Parameters

NameTypeDescription
fromaddressAddress from which tokens are burned
amountuint256Amount burned in wei (18 decimals)
burneraddressAddress that performed the burn (vault)

SupplyCapUpdated

Emitted when the supply limit is modified

Emitted when governance updates the maximum supply

event SupplyCapUpdated(uint256 oldCap, uint256 newCap);

Parameters

NameTypeDescription
oldCapuint256Old supply limit in wei (18 decimals)
newCapuint256New supply limit in wei (18 decimals)

RateLimitsUpdated

Emitted when rate limits are updated

OPTIMIZED: Indexed parameter type for efficient filtering

event RateLimitsUpdated(string indexed limitType, uint256 mintLimit, uint256 burnLimit);

Parameters

NameTypeDescription
limitTypestring
mintLimituint256New mint rate limit in wei per hour (18 decimals)
burnLimituint256New burn rate limit in wei per hour (18 decimals)

TreasuryUpdated

Emitted when treasury address is updated

event TreasuryUpdated(address indexed treasury);

Parameters

NameTypeDescription
treasuryaddressNew treasury address

AddressBlacklisted

Emitted when an address is blacklisted

OPTIMIZED: Indexed reason for efficient filtering by blacklist type

event AddressBlacklisted(address indexed account, string indexed reason);

Parameters

NameTypeDescription
accountaddressAddress that was blacklisted
reasonstringReason for blacklisting (for compliance records)

AddressUnblacklisted

Emitted when an address is removed from blacklist

Emitted when COMPLIANCE_ROLE removes an address from blacklist

event AddressUnblacklisted(address indexed account);

Parameters

NameTypeDescription
accountaddressAddress that was removed from blacklist

AddressWhitelisted

Emitted when an address is whitelisted

Emitted when COMPLIANCE_ROLE whitelists an address

event AddressWhitelisted(address indexed account);

Parameters

NameTypeDescription
accountaddressAddress that was whitelisted

AddressUnwhitelisted

Emitted when an address is removed from whitelist

Emitted when COMPLIANCE_ROLE removes an address from whitelist

event AddressUnwhitelisted(address indexed account);

Parameters

NameTypeDescription
accountaddressAddress that was removed from whitelist

WhitelistModeToggled

Emitted when whitelist mode is toggled

Emitted when COMPLIANCE_ROLE toggles whitelist mode

event WhitelistModeToggled(bool enabled);

Parameters

NameTypeDescription
enabledboolWhether whitelist mode is enabled

MinPricePrecisionUpdated

Emitted when minimum price precision is updated

Emitted when governance updates minimum price precision

event MinPricePrecisionUpdated(uint256 oldPrecision, uint256 newPrecision);

Parameters

NameTypeDescription
oldPrecisionuint256Old minimum precision value
newPrecisionuint256New minimum precision value

RateLimitReset

Emitted when rate limit is reset

OPTIMIZED: Indexed block number for efficient block-based filtering

event RateLimitReset(uint256 indexed blockNumber);

Parameters

NameTypeDescription
blockNumberuint256Block number when reset occurred

ETHRecovered

Emitted when ETH is recovered to treasury

event ETHRecovered(address indexed to, uint256 indexed amount);

Parameters

NameTypeDescription
toaddressAddress to which ETH was recovered
amountuint256Amount of ETH recovered

FeeCollectorUpdated

Emitted when FeeCollector address is updated

event FeeCollectorUpdated(address indexed oldFeeCollector, address indexed newFeeCollector);

Parameters

NameTypeDescription
oldFeeCollectoraddressPrevious FeeCollector address
newFeeCollectoraddressNew FeeCollector address

Structs

RateLimitCaps

Packed rate limit caps for mint and burn (per hour)

Two uint128 packed into one slot for storage efficiency

struct RateLimitCaps {
    uint128 mint;
    uint128 burn;
}

RateLimitInfo

Rate limiting information - OPTIMIZED: Packed for storage efficiency

Resets every ~300 blocks (~1 hour assuming 12 second blocks) or when rate limits are updated

Used to enforce mintRateLimit and burnRateLimit

struct RateLimitInfo {
    uint96 currentHourMinted; // Current minted amount in the current hour (12 bytes)
    uint96 currentHourBurned; // Current burned amount in the current hour (12 bytes)
    uint64 lastRateLimitReset; // Block number of the last rate limit reset (8 bytes)
}

QTIToken

Git Source

Inherits: Initializable, ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, SecureUpgradeable, IVersioned

Title: QTIToken

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Governance token for Quantillon Protocol with vote-escrow mechanics

Main characteristics:

  • Standard ERC20 with 18 decimals
  • Vote-escrow (ve) mechanics for governance power
  • Progressive decentralization through governance
  • Emergency pause mechanism for crisis situations
  • Upgradeable via UUPS pattern
  • Fixed supply cap for tokenomics
  • Governance proposal and voting system
  • Lock-based voting power calculation

Vote-escrow mechanics:

  • Users can lock QTI tokens for governance power
  • Longer locks = higher voting power (up to 4x multiplier)
  • Minimum lock: 7 days, Maximum lock: 365 days (1 year)
  • Voting power decreases linearly over time
  • Locked tokens cannot be transferred until unlock

Governance features:

  • Proposal creation with minimum threshold
  • Voting period with configurable duration
  • Vote counting and execution
  • Proposal cancellation and emergency actions

Security features:

  • Role-based access control for all critical operations
  • Emergency pause mechanism for crisis situations
  • Upgradeable architecture for future improvements
  • Secure vote-escrow mechanics
  • Proposal execution safeguards

Tokenomics:

  • Total supply: 100,000,000 QTI (fixed cap)
  • Initial distribution: Through protocol mechanisms
  • Decimals: 18 (standard for ERC20 tokens)
  • Governance power: Based on locked amount and duration

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

Role for governance operations (proposal creation, execution)

keccak256 hash avoids role collisions with other contracts

Should be assigned to governance multisig or DAO

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

Role for emergency operations (pause, emergency proposals)

keccak256 hash avoids role collisions with other contracts

Should be assigned to emergency multisig

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

MAX_LOCK_TIME

Maximum lock time for QTI tokens

Prevents extremely long locks that could impact governance

uint256 public constant MAX_LOCK_TIME = 365 days

MAX_BATCH_SIZE

Maximum batch size for lock operations to prevent DoS

Prevents out-of-gas attacks through large arrays

uint256 public constant MAX_BATCH_SIZE = 100

MAX_UNLOCK_BATCH_SIZE

Maximum batch size for unlock operations to prevent DoS

Prevents out-of-gas attacks through large user arrays

uint256 public constant MAX_UNLOCK_BATCH_SIZE = 50

MAX_VOTE_BATCH_SIZE

Maximum batch size for voting operations to prevent DoS

Prevents out-of-gas attacks through large proposal arrays

uint256 public constant MAX_VOTE_BATCH_SIZE = 50

MIN_LOCK_TIME

Minimum lock time for vote-escrow (1 week)

Prevents very short locks that could manipulate governance

Value: 7 days

uint256 public constant MIN_LOCK_TIME = 7 days

WEEK

Week duration in seconds (7 days)

Used for time calculations and voting periods

Value: 7 days = 604,800 seconds

uint256 public constant WEEK = 7 days

MAX_VE_QTI_MULTIPLIER

Maximum voting power multiplier (4x)

Maximum voting power a user can achieve through locking

Value: 4 (400% voting power for maximum lock)

uint256 public constant MAX_VE_QTI_MULTIPLIER = 4

MAX_TIME_ELAPSED

Maximum time elapsed for calculations to prevent manipulation

Caps time-based calculations to prevent timestamp manipulation

uint256 public constant MAX_TIME_ELAPSED = 10 * 365 days

PROPOSAL_EXECUTION_DELAY

Mandatory delay between a proposal's voting end and its execution

Post-vote governance timelock. A passed proposal cannot execute until this delay has elapsed after endTime, giving the community time to react to a malicious proposal before it self-executes role-gated changes. Fixed (not a storage variable) to avoid a storage-layout change on the live proxy; adjustable later via upgrade if needed.

uint256 public constant PROPOSAL_EXECUTION_DELAY = 2 days

TOTAL_SUPPLY_CAP

Total supply cap (100 million QTI)

Fixed supply cap for tokenomics

Value: 100,000,000 * 10^18 = 100,000,000 QTI

uint256 public constant TOTAL_SUPPLY_CAP = 100_000_000 * 1e18

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

State Variables

locks

Vote-escrow locks per user address

Maps user addresses to their lock information

Used to track locked tokens and voting power

mapping(address => LockInfo) public locks

totalLocked

Total QTI tokens locked in vote-escrow

Sum of all locked amounts across all users

Used for protocol analytics and governance metrics

uint256 public totalLocked

totalVotingPower

Total voting power across all locked tokens

Sum of all voting power across all users

Used for governance quorum calculations

uint256 public totalVotingPower

proposals

Governance proposals by proposal ID

Maps proposal IDs to proposal data

Used to store and retrieve proposal information

mapping(uint256 => Proposal) public proposals

nextProposalId

Next proposal ID to be assigned

Auto-incremented for each new proposal

Used to generate unique proposal identifiers

uint256 public nextProposalId

proposalThreshold

Minimum QTI required to create a governance proposal

Prevents spam proposals and ensures serious governance participation

Can be updated by governance

uint256 public proposalThreshold

minVotingPeriod

Minimum voting period duration

Ensures adequate time for community discussion and voting

Can be updated by governance

uint256 public minVotingPeriod

maxVotingPeriod

Maximum voting period duration

Prevents excessively long voting periods

Can be updated by governance

uint256 public maxVotingPeriod

quorumVotes

Quorum required for proposal to pass

Minimum number of votes needed for a proposal to be considered valid

Can be updated by governance

uint256 public quorumVotes

treasury

Treasury address for protocol fees

Address where protocol fees are collected and distributed

Can be updated by governance

address public treasury

_flashLoanBalanceBefore

Balance before flash loan check (used by flashLoanProtection modifier)

uint256 private _flashLoanBalanceBefore

decentralizationStartTime

Progressive decentralization parameters

Start time for the decentralization process

Duration of the decentralization process

Current level of decentralization (0-10000)

uint256 public decentralizationStartTime

decentralizationDuration

uint256 public decentralizationDuration

currentDecentralizationLevel

uint256 public currentDecentralizationLevel

proposalExecutionTime

Execution time for each proposal (with random delay)

mapping(uint256 => uint256) public proposalExecutionTime

proposalExecutionHash

Execution hash for each proposal (for verification)

mapping(uint256 => bytes32) public proposalExecutionHash

proposalScheduled

Whether a proposal has been scheduled for execution

mapping(uint256 => bool) public proposalScheduled

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

flashLoanProtection

Modifier to protect against flash loan attacks

Uses the FlashLoanProtectionLibrary to check QTI balance consistency

modifier flashLoanProtection() ;

_flashLoanProtectionBefore

function _flashLoanProtectionBefore() private;

_flashLoanProtectionAfter

function _flashLoanProtectionAfter() private view;

constructor

Constructor for QTI token contract

Sets up the time provider and disables initializers for security

Notes:

  • security: Validates time provider address and disables initializers

  • validation: Validates input parameters and business logic constraints

  • state-changes: Sets immutable time provider and disables initializers

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderTimeProvider contract for centralized time management

_protocolTime

Returns canonical protocol time from this contract's TimeProvider

Overrides the SecureUpgradeable base, which returns block.timestamp.

Notes:

  • security: Reads the immutable TimeProvider set at construction

  • validation: None required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Canonical protocol time in seconds

initialize

Initializes the QTI token contract

Sets up the governance token with initial configuration and assigns roles to admin

Notes:

  • security: Validates all input addresses and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Initializes all contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin, address _treasury, address _timelock) public initializer;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and governance roles
_treasuryaddressTreasury address for protocol fees
_timelockaddressTimelock contract address for secure upgrades

lock

Locks QTI tokens for a specified duration to earn voting power (veQTI)

Longer lock periods generate more voting power via time-weighted calculations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function lock(uint256 amount, uint256 lockTime) external whenNotPaused flashLoanProtection returns (uint256 veQTI);

Parameters

NameTypeDescription
amountuint256The amount of QTI tokens to lock
lockTimeuint256The duration to lock tokens (in seconds)

Returns

NameTypeDescription
veQTIuint256The amount of voting power (veQTI) earned from this lock

unlock

Unlock QTI tokens after lock period expires

Releases locked QTI tokens and removes voting power when lock period has expired

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unlock() external whenNotPaused returns (uint256 amount);

Returns

NameTypeDescription
amountuint256Amount of QTI unlocked

batchLock

Batch lock QTI tokens for voting power for multiple amounts

Efficiently locks multiple amounts with different lock times in a single transaction

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchLock(uint256[] calldata amounts, uint256[] calldata lockTimes)
    external
    whenNotPaused
    flashLoanProtection
    returns (uint256[] memory veQTIAmounts);

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations (must be >= MIN_LOCK_TIME)

Returns

NameTypeDescription
veQTIAmountsuint256[]Array of voting power calculated for each locked amount

_validateBatchLockInputs

Validates basic batch lock inputs

Ensures array lengths match and batch size is within limits

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _validateBatchLockInputs(uint256[] calldata amounts, uint256[] calldata lockTimes) internal pure;

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations

_validateAndCalculateTotalAmount

Validates all amounts and lock times, returns total amount

Ensures all amounts and lock times are valid and calculates total amount

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _validateAndCalculateTotalAmount(uint256[] calldata amounts, uint256[] calldata lockTimes)
    internal
    pure
    returns (uint256 totalAmount);

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations

Returns

NameTypeDescription
totalAmountuint256Total amount of QTI to be locked

_processBatchLocks

Processes all locks and calculates totals

Processes batch lock operations and calculates total voting power and amounts

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _processBatchLocks(
    uint256[] calldata amounts,
    uint256[] calldata lockTimes,
    uint256[] memory veQTIAmounts,
    LockInfo storage lockInfo
) internal returns (uint256 totalNewVotingPower, uint256 totalNewAmount);

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations
veQTIAmountsuint256[]Array to store calculated voting power amounts
lockInfoLockInfoStorage reference to user's lock information

Returns

NameTypeDescription
totalNewVotingPoweruint256Total new voting power from all locks
totalNewAmountuint256Total new amount locked

_calculateUnlockTime

Calculates unlock time with proper validation

Calculates new unlock time based on current timestamp and lock duration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateUnlockTime(uint256 currentTimestamp, uint256 lockTime, uint256 existingUnlockTime)
    internal
    pure
    returns (uint256 newUnlockTime);

Parameters

NameTypeDescription
currentTimestampuint256Current timestamp for calculation
lockTimeuint256Duration to lock tokens
existingUnlockTimeuint256Existing unlock time if already locked

Returns

NameTypeDescription
newUnlockTimeuint256Calculated unlock time

_calculateVotingPower

Calculates voting power with overflow protection

Calculates voting power based on amount and lock time with overflow protection

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateVotingPower(uint256 amount, uint256 lockTime) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256Amount of QTI tokens to lock
lockTimeuint256Duration to lock tokens

Returns

NameTypeDescription
<none>uint256votingPower Calculated voting power

_updateLockInfo

Updates lock info with overflow checks

Updates user's lock information with new amounts and times

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _updateLockInfo(
    LockInfo storage lockInfo,
    uint256 totalNewAmount,
    uint256 newUnlockTime,
    uint256 totalNewVotingPower,
    uint256 lockTime
) internal;

Parameters

NameTypeDescription
lockInfoLockInfoStorage reference to user's lock information
totalNewAmountuint256Total new amount to lock
newUnlockTimeuint256New unlock time
totalNewVotingPoweruint256Total new voting power
lockTimeuint256Lock duration

_updateGlobalTotalsAndTransfer

Updates global totals and transfers tokens

Updates global locked amounts and voting power, then transfers tokens

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _updateGlobalTotalsAndTransfer(uint256 totalAmount, uint256 oldVotingPower, uint256 totalNewVotingPower)
    internal;

Parameters

NameTypeDescription
totalAmountuint256Total amount of tokens to lock
oldVotingPoweruint256Previous voting power
totalNewVotingPoweruint256New total voting power

batchUnlock

Batch unlock QTI tokens for multiple users (admin function)

Efficiently unlocks tokens for multiple users in a single transaction

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function batchUnlock(address[] calldata users)
    external
    onlyRole(GOVERNANCE_ROLE)
    whenNotPaused
    returns (uint256[] memory amounts);

Parameters

NameTypeDescription
usersaddress[]Array of user addresses to unlock for

Returns

NameTypeDescription
amountsuint256[]Array of QTI amounts unlocked

_processOneBatchUnlock

Unlocks one user's lock and transfers tokens (used by batchUnlock to reduce stack depth)

Clears lock state, transfers QTI from contract to user, emits TokensUnlocked and VotingPowerUpdated

Notes:

  • security: Lock expiry and non-zero amount checked; internal only

  • validation: unlockTime <= currentTimestamp, lockInfo.amount > 0

  • state-changes: locks[user], _transfer

  • events: TokensUnlocked, VotingPowerUpdated

  • errors: LockNotExpired, NothingToUnlock

  • reentrancy: ERC20 transfer; caller expected under nonReentrant

  • access: Internal

  • oracle: None; timestamp passed in

function _processOneBatchUnlock(address user, uint256 currentTimestamp)
    internal
    returns (uint256 amount, uint256 oldVotingPower);

Parameters

NameTypeDescription
useraddressAddress to unlock for
currentTimestampuint256Current time from TimeProvider

Returns

NameTypeDescription
amountuint256Amount unlocked
oldVotingPoweruint256Voting power removed

batchTransfer

Batch transfer QTI tokens to multiple addresses

Efficiently transfers tokens to multiple recipients in a single transaction

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: No access restrictions

  • oracle: No oracle dependencies

function batchTransfer(address[] calldata recipients, uint256[] calldata amounts)
    external
    whenNotPaused
    flashLoanProtection
    returns (bool);

Parameters

NameTypeDescription
recipientsaddress[]Array of recipient addresses
amountsuint256[]Array of amounts to transfer

Returns

NameTypeDescription
<none>boolsuccess True if all transfers were successful

getVotingPower

Get voting power for an address with linear decay

Calculates current voting power with linear decay over time

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getVotingPower(address user) external view returns (uint256 votingPower);

Parameters

NameTypeDescription
useraddressAddress to get voting power for

Returns

NameTypeDescription
votingPoweruint256Current voting power of the user (decays linearly over time)

updateVotingPower

Update voting power for the caller based on current time

Updates voting power based on current time and lock duration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateVotingPower() external returns (uint256 newVotingPower);

Returns

NameTypeDescription
newVotingPoweruint256Updated voting power

getLockInfo

Get lock info for an address

Returns comprehensive lock information for a user

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getLockInfo(address user)
    external
    view
    returns (
        uint256 amount,
        uint256 unlockTime,
        uint256 votingPower,
        uint256 lastClaimTime,
        uint256 initialVotingPower,
        uint256 lockTime
    );

Parameters

NameTypeDescription
useraddressAddress to get lock info for

Returns

NameTypeDescription
amountuint256Locked QTI amount
unlockTimeuint256Timestamp when lock expires
votingPoweruint256Current voting power
lastClaimTimeuint256Last claim time (for future use)
initialVotingPoweruint256Initial voting power when locked
lockTimeuint256Original lock duration

createProposal

Create a new governance proposal

Creates a new governance proposal with specified parameters and voting period

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: No oracle dependencies

function createProposal(string calldata description, uint256 votingPeriod, bytes calldata data)
    external
    whenNotPaused
    returns (uint256 proposalId);

Parameters

NameTypeDescription
descriptionstringProposal description
votingPerioduint256Voting period in seconds
databytesExecution data (function calls)

Returns

NameTypeDescription
proposalIduint256Unique identifier for the created proposal

vote

Vote on a proposal

Allows users to vote on governance proposals with their voting power

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function vote(uint256 proposalId, bool support) external whenNotPaused;

Parameters

NameTypeDescription
proposalIduint256Proposal ID
supportboolTrue for yes, false for no

batchVote

Batch vote on multiple proposals

Efficiently votes on multiple proposals in a single transaction

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchVote(uint256[] calldata proposalIds, bool[] calldata supportVotes)
    external
    whenNotPaused
    flashLoanProtection;

Parameters

NameTypeDescription
proposalIdsuint256[]Array of proposal IDs to vote on
supportVotesbool[]Array of vote directions (true for yes, false for no)

executeProposal

Execute a successful proposal

Executes a proposal that has passed voting and meets quorum requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function executeProposal(uint256 proposalId) external nonReentrant;

Parameters

NameTypeDescription
proposalIduint256Proposal ID

getProposalExecutionInfo

Get execution information for a scheduled proposal

Returns execution status and timing information for a proposal

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getProposalExecutionInfo(uint256 proposalId)
    external
    view
    returns (bool scheduled, uint256 executionTime, bool canExecute);

Parameters

NameTypeDescription
proposalIduint256Proposal ID

Returns

NameTypeDescription
scheduledboolWhether the proposal is scheduled
executionTimeuint256When the proposal can be executed
canExecuteboolWhether the proposal can be executed now

getProposalExecutionHash

Get the execution hash for a scheduled proposal

Returns the execution hash required to execute a scheduled proposal

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getProposalExecutionHash(uint256 proposalId) external view returns (bytes32 executionHash);

Parameters

NameTypeDescription
proposalIduint256Proposal ID

Returns

NameTypeDescription
executionHashbytes32Hash required to execute the proposal

cancelProposal

Cancel a proposal (only proposer or admin)

Allows proposer or admin to cancel a proposal before execution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function cancelProposal(uint256 proposalId) external;

Parameters

NameTypeDescription
proposalIduint256Proposal ID

getProposal

Get proposal details

Returns comprehensive proposal information including voting results

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getProposal(uint256 proposalId)
    external
    view
    returns (
        address proposer,
        uint256 startTime,
        uint256 endTime,
        uint256 forVotes,
        uint256 againstVotes,
        bool executed,
        bool canceled,
        string memory description
    );

Parameters

NameTypeDescription
proposalIduint256Proposal ID

Returns

NameTypeDescription
proposeraddressAddress of the proposer
startTimeuint256Timestamp when voting starts
endTimeuint256Timestamp when voting ends
forVotesuint256Total votes in favor
againstVotesuint256Total votes against
executedboolWhether the proposal was executed
canceledboolWhether the proposal was canceled
descriptionstringProposal description

getReceipt

Get voting receipt for a user

Returns voting information for a specific user on a specific proposal

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getReceipt(uint256 proposalId, address voter)
    external
    view
    returns (bool hasVoted, bool support, uint256 votes);

Parameters

NameTypeDescription
proposalIduint256Proposal ID
voteraddressAddress of the voter

Returns

NameTypeDescription
hasVotedboolWhether the user has voted
supportboolTrue for yes vote, false for no vote
votesuint256Number of votes cast

updateGovernanceParameters

Update governance parameters

Updates governance parameters including proposal threshold, voting period, and quorum

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateGovernanceParameters(uint256 _proposalThreshold, uint256 _minVotingPeriod, uint256 _quorumVotes)
    external
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_proposalThresholduint256New minimum QTI required to propose
_minVotingPerioduint256New minimum voting period
_quorumVotesuint256New quorum required for proposals to pass

updateTreasury

Update treasury address

Updates the treasury address for protocol fee collection

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateTreasury(address _treasury) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

updateDecentralizationLevel

Update decentralization level

This function is intended to be called periodically by the governance to update the decentralization level based on the elapsed time. Includes bounds checking to prevent timestamp manipulation.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateDecentralizationLevel() external onlyRole(GOVERNANCE_ROLE);

_calculateVotingPowerMultiplier

Calculate voting power multiplier based on lock time

Calculates linear multiplier from 1x to 4x based on lock duration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateVotingPowerMultiplier(uint256 lockTime) internal pure returns (uint256);

Parameters

NameTypeDescription
lockTimeuint256Duration of the lock

Returns

NameTypeDescription
<none>uint256multiplier Voting power multiplier

_effectiveLockDuration

Derives the effective lock duration of a (merged) position from its unlock time

Used by lock()/batchLock() so a top-up recomputes voting power over the FULL merged position against its remaining lock duration, clamped to [MIN_LOCK_TIME, MAX_LOCK_TIME]. For a fresh lock this returns exactly the supplied lockTime, preserving prior behavior.

Notes:

  • security: Pure-ish read of TimeProvider; no external state mutation

  • validation: Clamps to [MIN_LOCK_TIME, MAX_LOCK_TIME] so the multiplier stays in range

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _effectiveLockDuration(uint256 unlockTime) internal view returns (uint256 duration);

Parameters

NameTypeDescription
unlockTimeuint256Absolute unlock timestamp of the merged position

Returns

NameTypeDescription
durationuint256Effective remaining lock duration in seconds, clamped to valid bounds

_updateVotingPower

Update voting power for a user based on current time

Updates voting power based on current time and lock duration with linear decay

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _updateVotingPower(address user) internal returns (uint256 newVotingPower);

Parameters

NameTypeDescription
useraddressAddress of the user to update

Returns

NameTypeDescription
newVotingPoweruint256Updated voting power

decimals

Returns the number of decimals for the QTI token

Always returns 18 for standard ERC20 compatibility

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function decimals() public pure override returns (uint8);

Returns

NameTypeDescription
<none>uint8The number of decimals (18)

pause

Pauses all token operations including transfers and governance

Emergency function to halt all contract operations when needed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpauses all token operations

Resumes normal contract operations after emergency is resolved

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external onlyRole(EMERGENCY_ROLE);

recoverToken

Recover accidentally sent tokens to treasury only

Recovers accidentally sent tokens to the treasury address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to recover

recoverETH

Recover accidentally sent ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

getGovernanceInfo

Get current governance information

Returns comprehensive governance information including totals and parameters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getGovernanceInfo()
    external
    view
    returns (
        uint256 totalLocked_,
        uint256 totalVotingPower_,
        uint256 proposalThreshold_,
        uint256 quorumVotes_,
        uint256 currentDecentralizationLevel_
    );

Returns

NameTypeDescription
totalLocked_uint256Total QTI tokens locked in vote-escrow
totalVotingPower_uint256Total voting power across all locked tokens
proposalThreshold_uint256Minimum QTI required to propose
quorumVotes_uint256Quorum required for proposals to pass
currentDecentralizationLevel_uint256Current decentralization level (0-10000)

Events

TokensLocked

Emitted when tokens are locked for voting power

OPTIMIZED: Indexed amount and unlockTime for efficient filtering

event TokensLocked(address indexed user, uint256 indexed amount, uint256 indexed unlockTime, uint256 votingPower);

Parameters

NameTypeDescription
useraddressAddress of the user who locked tokens
amountuint256Amount of QTI locked
unlockTimeuint256Timestamp when the lock expires
votingPoweruint256Voting power calculated for the locked amount

TokensUnlocked

Emitted when tokens are unlocked after lock period expires

OPTIMIZED: Indexed amount for efficient filtering by unlock size

event TokensUnlocked(address indexed user, uint256 indexed amount, uint256 votingPower);

Parameters

NameTypeDescription
useraddressAddress of the user who unlocked tokens
amountuint256Amount of QTI unlocked
votingPoweruint256Voting power before unlocking

VotingPowerUpdated

Emitted when voting power for an address is updated

event VotingPowerUpdated(address indexed user, uint256 oldPower, uint256 newPower);

Parameters

NameTypeDescription
useraddressAddress of the user whose voting power changed
oldPoweruint256Previous voting power
newPoweruint256New voting power

ProposalCreated

Emitted when a new governance proposal is created

event ProposalCreated(uint256 indexed proposalId, address indexed proposer, string description);

Parameters

NameTypeDescription
proposalIduint256Unique identifier for the proposal
proposeraddressAddress of the proposer
descriptionstringDescription of the proposal

Voted

Emitted when a user votes on a proposal

OPTIMIZED: Indexed support for efficient filtering by vote direction

event Voted(uint256 indexed proposalId, address indexed voter, bool indexed support, uint256 votes);

Parameters

NameTypeDescription
proposalIduint256Unique identifier for the proposal
voteraddressAddress of the voter
supportboolTrue for yes vote, false for no vote
votesuint256Number of votes cast

ProposalExecuted

Emitted when a proposal is successfully executed

event ProposalExecuted(uint256 indexed proposalId);

Parameters

NameTypeDescription
proposalIduint256Unique identifier for the executed proposal

ProposalCanceled

Emitted when a proposal is canceled

event ProposalCanceled(uint256 indexed proposalId);

Parameters

NameTypeDescription
proposalIduint256Unique identifier for the canceled proposal

GovernanceParametersUpdated

Emitted when governance parameters are updated

OPTIMIZED: Indexed parameter type for efficient filtering

event GovernanceParametersUpdated(
    string indexed parameterType, uint256 proposalThreshold, uint256 minVotingPeriod, uint256 quorumVotes
);

Parameters

NameTypeDescription
parameterTypestring
proposalThresholduint256New minimum QTI required to propose
minVotingPerioduint256New minimum voting period
quorumVotesuint256New quorum required for proposals to pass

DecentralizationLevelUpdated

Emitted when the decentralization level is updated

OPTIMIZED: Indexed level for efficient filtering by decentralization stage

event DecentralizationLevelUpdated(uint256 indexed newLevel);

Parameters

NameTypeDescription
newLeveluint256New decentralization level (0-10000)

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 indexed amount);

Parameters

NameTypeDescription
toaddressRecipient address
amountuint256Amount of ETH recovered

Structs

BatchLockState

Vote-escrow lock information for each user

Stores locked amount, unlock time, voting power, and claim time

Used to calculate governance power and manage locks

OPTIMIZED: Fields ordered for optimal storage packing

struct BatchLockState {
    uint256 currentTimestamp;
    uint256 existingUnlockTime;
    uint256 finalUnlockTime;
    uint256 finalLockTime;
    uint256 newUnlockTime;
    uint256 newVotingPower;
}

LockInfo

struct LockInfo {
    uint96 amount; // Locked QTI amount in wei (18 decimals) - 12 bytes
    uint96 votingPower; // Current voting power (calculated) - 12 bytes
    uint96 initialVotingPower; // Initial voting power when locked - 12 bytes
    uint32 unlockTime; // Timestamp when lock expires - 4 bytes
    uint32 lastClaimTime; // Last claim time (for future use) - 4 bytes
    uint32 lockTime; // Original lock duration - 4 bytes
}

Proposal

Governance proposal structure

Stores all proposal data including voting results and execution info

Used for governance decision making

struct Proposal {
    address proposer; // Address that created the proposal
    uint256 startTime; // Timestamp when voting starts
    uint256 endTime; // Timestamp when voting ends
    uint256 forVotes; // Total votes in favor
    uint256 againstVotes; // Total votes against
    bool executed; // Whether proposal was executed
    bool canceled; // Whether proposal was canceled
    string description; // Human-readable proposal description
    bytes data; // Execution data (function calls)
    mapping(address => Receipt) receipts; // Individual voting receipts
}

Receipt

Voting receipt for each voter in a proposal

Stores individual voting information for each user

Used to prevent double voting and track individual votes

struct Receipt {
    bool hasVoted; // Whether user has voted on this proposal
    bool support; // True for yes vote, false for no vote
    uint256 votes; // Number of votes cast (voting power used)
}

QuantillonVault

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IVersioned

Title: QuantillonVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Main vault managing QEURO minting against USDC collateral

Main characteristics:

  • Simple USDC to QEURO swap mechanism
  • USDC as input for QEURO minting
  • Real-time EUR/USD price oracle integration
  • Dynamic fee structure for protocol sustainability
  • Emergency pause mechanism for crisis situations
  • Upgradeable via UUPS pattern

Minting mechanics:

  • Users swap USDC for QEURO
  • QEURO is minted based on EUR/USD exchange rate
  • Minting fees charged for protocol revenue
  • Simple 1:1 exchange with price conversion
  • Price deviation protection prevents flash loan manipulation
  • Block-based validation ensures price freshness

Redemption mechanics:

  • Users can redeem QEURO back to USDC
  • Redemption based on current EUR/USD exchange rate
  • Protocol fees charged on redemptions
  • USDC returned to user after fee deduction
  • Same price deviation protection as minting
  • Consistent security across all operations

Risk management:

  • Real-time price monitoring
  • Emergency pause capabilities
  • Slippage protection on swaps
  • Flash loan attack prevention via price deviation checks
  • Block-based price manipulation detection
  • Comprehensive oracle validation and fallback mechanisms

Fee structure:

  • Minting fees for creating QEURO
  • Redemption fees for converting QEURO back to USDC
  • Dynamic fee adjustment based on market conditions

Security features:

  • Role-based access control for all critical operations
  • Reentrancy protection for all external calls
  • Emergency pause mechanism for crisis situations
  • Upgradeable architecture for future improvements
  • Secure collateral management
  • Oracle price validation
  • Flash loan protection through price deviation checks
  • Block-based price update validation
  • Comprehensive price manipulation attack prevention

Integration points:

  • QEURO token for minting and burning
  • USDC for collateral deposits and withdrawals
  • Chainlink oracle for EUR/USD price feeds
  • Vault math library for precise calculations

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

Role for governance operations (parameter updates, emergency actions)

keccak256 hash avoids role collisions with other contracts

Should be assigned to governance multisig or DAO

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

Role for emergency operations (pause)

keccak256 hash avoids role collisions with other contracts

Should be assigned to emergency multisig

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

VAULT_OPERATOR_ROLE

Role for vault operators (UserPool) to trigger Aave deployments

keccak256 hash avoids role collisions with other contracts

Should be assigned to UserPool contract

bytes32 public constant VAULT_OPERATOR_ROLE = keccak256("VAULT_OPERATOR_ROLE")

YIELD_DISTRIBUTOR_ROLE

Role allowed to credit harvested user yield into stQEURO vaults.

bytes32 public constant YIELD_DISTRIBUTOR_ROLE = keccak256("YIELD_DISTRIBUTOR_ROLE")

MAX_PRICE_DEVIATION

Maximum allowed price deviation between consecutive price updates (in basis points)

Prevents flash loan price manipulation attacks

200 basis points = 2% maximum deviation

uint256 private constant MAX_PRICE_DEVIATION = 200

MIN_BLOCKS_BETWEEN_UPDATES

Minimum number of blocks required between price updates for deviation checks

Prevents manipulation within the same block

uint256 private constant MIN_BLOCKS_BETWEEN_UPDATES = 1

MIN_COLLATERALIZATION_RATIO_FOR_MINTING

uint256 private constant MIN_COLLATERALIZATION_RATIO_FOR_MINTING = 105e18

CRITICAL_COLLATERALIZATION_RATIO_BPS

uint256 private constant CRITICAL_COLLATERALIZATION_RATIO_BPS = 10100

MIN_ALLOWED_COLLATERALIZATION_RATIO

uint256 private constant MIN_ALLOWED_COLLATERALIZATION_RATIO = 101e18

MIN_ALLOWED_CRITICAL_RATIO

uint256 private constant MIN_ALLOWED_CRITICAL_RATIO = 100e18

QEURO_DUST_THRESHOLD

QEURO supply at or below 1e-6 QEURO is unredeemable rounding dust and is treated as empty only by pre-operation status checks. Projected mint collateralization still uses the full raw supply, so this tolerance cannot bypass the post-mint 105% floor. Keep this boundary aligned with HedgerPool.QEURO_DUST_THRESHOLD.

uint256 private constant QEURO_DUST_THRESHOLD = 1e12

MAX_HEDGER_REWARD_FEE_SPLIT

Maximum value allowed for hedgerRewardFeeSplit

uint256 private constant MAX_HEDGER_REWARD_FEE_SPLIT = 1e18

DEV_MODE_DELAY

Minimum delay before a proposed dev-mode change takes effect

uint256 private constant DEV_MODE_DELAY = 48 hours

State Variables

qeuro

QEURO token contract for minting and burning

Used for all QEURO minting and burning operations

Should be the official QEURO token contract

IQEUROToken public qeuro

usdc

USDC token used as collateral

Used for all collateral deposits, withdrawals, and fee payments

Should be the official USDC contract on the target network

IERC20 public usdc

oracle

Oracle contract for EUR/USD price feeds (Chainlink or Stork via router)

Provides real-time EUR/USD exchange rates for minting and redemption

Used for price calculations in swap operations

IOracle public oracle

hedgerPool

HedgerPool contract for collateralization checks

Used to verify protocol has sufficient hedging positions before minting QEURO

Ensures protocol is properly collateralized by hedgers

IHedgerPool public hedgerPool

userPool

UserPool contract for user deposit tracking

Used to get total user deposits for collateralization ratio calculations

Required for accurate protocol collateralization assessment

IUserPool public userPool

treasury

Treasury address for ETH recovery

SECURITY: Only this address can receive ETH from recoverETH function

address public treasury

feeCollector

Fee collector contract for protocol fees

Centralized fee collection and distribution

address public feeCollector

_flashLoanBalanceBefore

USDC balance before flash loan check (used by flashLoanProtection modifier)

uint256 private _flashLoanBalanceBefore

defaultStakingVaultId

Default vault id used for automatic deployment after minting.

uint256 public defaultStakingVaultId

totalUsdcInExternalVaults

Total principal deployed across all external staking vaults.

uint256 public totalUsdcInExternalVaults

stakingVaultAdapterById

External staking vault adapter by vault id.

mapping(uint256 => IExternalStakingVault) private stakingVaultAdapterById

principalUsdcByVaultId

Tracked principal deployed to each external staking vault.

mapping(uint256 => uint256) private principalUsdcByVaultId

stakingVaultActiveById

Active flag for configured external staking vault ids.

mapping(uint256 => bool) private stakingVaultActiveById

redemptionPriorityVaultIds

Ordered list of active vault ids used for redemption liquidity sourcing.

uint256[] private redemptionPriorityVaultIds

stQEUROFactory

stQEURO factory used to register this vault's staking token.

address public stQEUROFactory

stQEUROTokenByVaultId

stQEURO token address registered per vault id.

mapping(uint256 => address) public stQEUROTokenByVaultId

mintFee

Protocol fee charged on minting QEURO

Fee denominated in 1e18 precision — 1e16 = 1%, 1e18 = 100% (NOT basis points)

Revenue source for the protocol

uint256 public mintFee

redemptionFee

Protocol fee charged on redeeming QEURO

Fee denominated in 1e18 precision — 1e16 = 1%, 1e18 = 100% (NOT basis points)

Revenue source for the protocol

uint256 public redemptionFee

hedgerRewardFeeSplit

Share of protocol fees routed to HedgerPool reward reserve (1e18 = 100%)

uint256 public hedgerRewardFeeSplit

minCollateralizationRatioForMinting

Minimum collateralization ratio required for minting QEURO (in 1e18 precision, NOT basis points)

Example: 105000000000000000000 = 105% collateralization ratio required for minting

When protocol collateralization >= this threshold, minting is allowed

When protocol collateralization < this threshold, minting is halted

Can be updated by governance to adjust protocol risk parameters

Stored in 18 decimals format (e.g., 105000000000000000000 = 105.000000%)

uint256 public minCollateralizationRatioForMinting

criticalCollateralizationRatio

Critical collateralization ratio that triggers liquidation (in 18 decimals)

Example: 101000000000000000000 = 101.000000% collateralization ratio triggers liquidation

When protocol collateralization < this threshold, hedgers start being liquidated

Emergency threshold to protect protocol solvency

Can be updated by governance to adjust liquidation triggers

Stored in 18 decimals format (e.g., 101000000000000000000 = 101.000000%)

uint256 public criticalCollateralizationRatio

totalUsdcHeld

Total USDC held in the vault

Used for vault analytics and risk management

uint256 public totalUsdcHeld

totalMinted

Total QEURO in circulation (minted by this vault)

uint256 public totalMinted

lastValidEurUsdPrice

Last valid EUR/USD price used in operations

Used for price deviation checks to prevent manipulation

uint256 private lastValidEurUsdPrice

lastPriceUpdateBlock

Block number of the last price update

Used to ensure minimum blocks between updates for deviation checks

uint256 private lastPriceUpdateBlock

devModeEnabled

Dev mode flag to disable price caching requirements

When enabled, price deviation checks and caching requirements are skipped (dev/testing only)

bool public devModeEnabled

pendingDevMode

Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

Timestamp at which pendingDevMode may be applied (0 = no pending proposal)

Deadline in seconds, compared against block.timestamp.

uint256 public devModePendingAt

lastPriceUpdateTime

Variable to store the timestamp of the last valid price update

uint256 private lastPriceUpdateTime

fundingRateAnnualBps

Retired annual funding value; preserved exclusively for proxy storage compatibility.

Never read for allocation and never reused as the staking yield haircut.

uint256 internal fundingRateAnnualBps

lastYieldHarvestByVaultId

Timestamp of the last yield harvest+distribution per vault id (keeper idempotency).

Set lazily on the first harvestAndDistributeVaultYield call for a vault id.

mapping(uint256 => uint256) internal lastYieldHarvestByVaultId

hedgerYieldRecipient

Recipient of the staking yield haircut; there is no hedger base allocation.

Falls back to treasury when unset (address(0)).

address internal hedgerYieldRecipient

executionPricing

Optional volume-dependent execution pricing; appended for proxy storage compatibility.

Zero before coordinated activation. All ordinary mint/redeem routes use this module.

IExecutionPricing public executionPricing

hedgerStakingYieldHaircutBps

Governance share of gross earned staking yield, in bps; zero on upgrade.

uint256 public hedgerStakingYieldHaircutBps

signedExecutionEnabled

Whether the configured module requires atomic signed settlement contexts.

bool public signedExecutionEnabled

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.1.0").

flashLoanProtection

Modifier to protect against flash loan attacks

Uses the FlashLoanProtectionLibrary to check USDC balance consistency

modifier flashLoanProtection() ;

onlySelf

modifier onlySelf() ;

_onlySelf

Reverts unless caller is this contract.

Internal guard used by onlySelf for explicit self-call commit functions.

Notes:

  • security: Prevents direct external invocation of commit-phase helpers.

  • validation: Requires msg.sender == address(this).

  • state-changes: None.

  • events: None.

  • errors: Reverts with NotAuthorized when caller is not self.

  • reentrancy: No external calls.

  • access: Internal helper used by modifier.

  • oracle: No oracle dependencies.

function _onlySelf() internal view;

_flashLoanProtectionBefore

function _flashLoanProtectionBefore() private;

_flashLoanProtectionAfter

function _flashLoanProtectionAfter() private view;

constructor

Constructor for QuantillonVault contract

Disables initializers for security

Notes:

  • security: Disables initializers for security

  • validation: No validation needed

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the vault with contracts and parameters

This function configures:

  1. Access roles
  2. References to external contracts
  3. Default protocol parameters
  4. Security (pause, reentrancy, upgrades)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Initializes all contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _oracle,
    address _hedgerPool,
    address _userPool,
    address _timelock,
    address _feeCollector
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_qeuroaddressAddress of the QEURO token contract
_usdcaddressAddress of the USDC token contract
_oracleaddressAddress of the Oracle contract
_hedgerPooladdressAddress of the HedgerPool contract
_userPooladdressAddress of the UserPool contract
_timelockaddressAddress of the timelock contract
_feeCollectoraddressAddress of the fee collector contract

mintQEURO

Mints QEURO tokens by swapping USDC

Minting process:

  1. Fetch EUR/USD price from oracle
  2. Calculate amount of QEURO to mint
  3. Transfer USDC from user
  4. Update vault balances
  5. Mint QEURO to user

Example: 1100 USDC → ~1000 QEURO (if EUR/USD = 1.10) Simple swap with protocol fee applied

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: No access restrictions

  • oracle: Requires fresh oracle price data

function mintQEURO(uint256 usdcAmount, uint256 minQeuroOut)
    external
    nonReentrant
    whenNotPaused
    flashLoanProtection;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to swap for QEURO
minQeuroOutuint256Minimum amount of QEURO expected (slippage protection)

mintQEUROToVault

Mints QEURO and routes deployed USDC to a specific external vault id.

Same mint flow as mintQEURO, but with explicit target vault routing.

Notes:

  • security: Protected by pause and reentrancy guards.

  • validation: Reverts on invalid routing id, slippage, oracle, or collateral checks.

  • state-changes: Updates mint accounting, fee routing, and optional external vault principal.

  • events: Emits mint and vault deployment events in downstream flow.

  • errors: Reverts on invalid inputs, oracle/CR checks, or integration failures.

  • reentrancy: Guarded by nonReentrant.

  • access: Public.

  • oracle: Requires valid oracle reads in mint flow.

function mintQEUROToVault(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId)
    external
    nonReentrant
    whenNotPaused
    flashLoanProtection;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC provided by caller (6 decimals).
minQeuroOutuint256Minimum acceptable QEURO output (18 decimals).
vaultIduint256Target staking vault id (0 disables auto-deploy routing).

mintAndStakeQEURO

Mints QEURO then stakes it into the stQEURO token for the selected vault id.

Executes mint flow to this contract, stakes into stQEUROTokenByVaultId[vaultId], then transfers stQEURO to caller.

Notes:

  • security: Protected by pause and reentrancy guards.

  • validation: Reverts on invalid vault id/token, slippage, and staking failures.

  • state-changes: Updates mint accounting, optional external deployment, and stQEURO balances.

  • events: Emits mint/deployment events and staking token events downstream.

  • errors: Reverts on mint, routing, approval, staking, or transfer failures.

  • reentrancy: Guarded by nonReentrant.

  • access: Public.

  • oracle: Requires valid oracle reads in mint flow.

function mintAndStakeQEURO(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId, uint256 minStQEUROOut)
    external
    nonReentrant
    whenNotPaused
    flashLoanProtection
    returns (uint256 qeuroMinted, uint256 stQEUROMinted);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC provided by caller (6 decimals).
minQeuroOutuint256Minimum acceptable QEURO output from mint (18 decimals).
vaultIduint256Target staking vault id used for routing and stQEURO token selection.
minStQEUROOutuint256Minimum acceptable stQEURO output from staking.

Returns

NameTypeDescription
qeuroMinteduint256QEURO minted before staking.
stQEUROMinteduint256stQEURO minted and sent to caller.

_mintQEUROFlow

Shared mint pipeline used by mint entrypoints.

Validates routing/oracle/collateral constraints, computes outputs, then dispatches commit phase.

Notes:

  • security: Enforces protocol collateralization, price deviation, and vault routing checks.

  • validation: Reverts on invalid addresses/amounts, invalid routing, or failed risk checks.

  • state-changes: Performs no direct writes until commit dispatch; writes occur in commit helper.

  • events: Emits no events directly; commit helper emits mint/deployment events.

  • errors: Reverts on any failed validation or risk check.

  • reentrancy: Called from guarded external entrypoints.

  • access: Internal helper.

  • oracle: Uses live oracle reads for mint pricing and checks.

function _mintQEUROFlow(
    address payer,
    address qeuroRecipient,
    uint256 usdcAmount,
    uint256 minQeuroOut,
    uint256 targetVaultId
) internal returns (uint256 qeuroToMint);

Parameters

NameTypeDescription
payeraddressAddress funding the USDC transfer.
qeuroRecipientaddressAddress receiving minted QEURO.
usdcAmountuint256Amount of USDC provided (6 decimals).
minQeuroOutuint256Minimum acceptable QEURO output (18 decimals).
targetVaultIduint256Vault id to auto-deploy net USDC principal into (0 disables routing).

Returns

NameTypeDescription
qeuroToMintuint256Final QEURO amount to mint.

_dispatchMintCommit

Dispatches mint commit through explicit self-call.

Preserves separation between validation/read phase and commit/interactions phase.

Notes:

  • security: Uses onlySelf-guarded commit entrypoint.

  • validation: Assumes payload was prepared by validated mint flow.

  • state-changes: No direct state changes in dispatcher.

  • events: No direct events in dispatcher.

  • errors: Propagates commit-phase revert reasons.

  • reentrancy: Called from guarded parent flow.

  • access: Internal helper.

  • oracle: No direct oracle reads.

function _dispatchMintCommit(MintCommitPayload memory payload) internal;

Parameters

NameTypeDescription
payloadMintCommitPayloadPacked mint commit payload.

_validateMintRouting

Validates mint routing parameters for external vault deployment.

targetVaultId == 0 is allowed and means no auto-deploy.

Notes:

  • security: Ensures routing only targets active, configured adapters.

  • validation: Reverts when non-zero vault id is inactive or adapter is unset.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with InvalidVault or ZeroAddress for invalid routing.

  • reentrancy: Not applicable for view function.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _validateMintRouting(uint256 targetVaultId) internal view;

Parameters

NameTypeDescription
targetVaultIduint256Vault id requested for principal deployment.

_getValidatedMintPrices

Fetches and validates oracle prices required for minting.

Reads EUR/USD and USDC/USD and verifies both are valid/non-zero.

Notes:

  • security: Rejects invalid oracle outputs before mint accounting.

  • validation: Reverts when oracle flags invalid or returns zero USDC/USD.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with InvalidOraclePrice.

  • reentrancy: External oracle reads only.

  • access: Internal helper.

  • oracle: Requires live oracle reads.

function _getValidatedMintPrices() internal returns (uint256 eurUsdPrice, bool isValid);

Returns

NameTypeDescription
eurUsdPriceuint256Validated EUR/USD price.
isValidboolValidity flag returned by oracle for EUR/USD.

_enforceMintEligibility

Enforces protocol-level mint eligibility constraints.

Requires initialized price cache, active hedger liquidity, and collateralization allowance. The collateralization gate is evaluated against the supplied live eurUsdPrice (not the cached price) so the binding mint decision is consistent with the price used for the rest of the mint computation. The public canMint() view remains a cached-price advisory.

Notes:

  • security: Prevents minting when safety prerequisites are unmet.

  • validation: Reverts when cache is uninitialized, no hedger liquidity, or CR check fails.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with protocol-specific eligibility errors.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: Uses the supplied live EUR/USD price for the collateralization gate.

function _enforceMintEligibility(uint256 eurUsdPrice) internal view;

Parameters

NameTypeDescription
eurUsdPriceuint256Live, validated EUR/USD price used to value QEURO debt for the CR gate (18 decimals).

_enforcePriceDeviation

Enforces the EUR/USD deviation guard unless dev mode is enabled.

Compares live price vs cached baseline and reverts when deviation exceeds the configured threshold. Shared by the mint and redeem flows so the guard exists once.

Notes:

  • security: Blocks mint/redeem during abnormal price moves outside policy limits.

  • validation: Reverts with ExcessiveSlippage when deviation rule is violated.

  • state-changes: No state changes.

  • events: Emits PriceDeviationDetected before reverting on violation.

  • errors: Reverts with ExcessiveSlippage.

  • reentrancy: No external calls besides pure library logic.

  • access: Internal helper.

  • oracle: Uses provided live oracle price and cached baseline.

function _enforcePriceDeviation(uint256 eurUsdPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Current validated EUR/USD price.

_computeMintAmounts

Computes mint fee, net USDC, and QEURO output.

Applies configured mint fee and slippage floor against minQeuroOut.

Notes:

  • security: Enforces minimum-output slippage protection.

  • validation: Reverts when computed output is below minQeuroOut.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with ExcessiveSlippage.

  • reentrancy: Not applicable for pure arithmetic helper.

  • access: Internal helper.

  • oracle: Uses supplied validated oracle input.

function _computeMintAmounts(uint256 usdcAmount, uint256 eurUsdPrice, uint256 minQeuroOut)
    internal
    returns (uint256 fee, uint256 netAmount, uint256 qeuroToMint);

Parameters

NameTypeDescription
usdcAmountuint256Gross USDC input (6 decimals).
eurUsdPriceuint256Validated EUR/USD price.
minQeuroOutuint256Minimum acceptable QEURO output.

Returns

NameTypeDescription
feeuint256Protocol fee deducted from usdcAmount.
netAmountuint256Net USDC backing minted QEURO.
qeuroToMintuint256QEURO output to mint.

_enforceProjectedCollateralizationFloor

Projected-CR guard against an arbitrary floor (18-dec ratio).

The mint path uses the 105% minting floor, but the yield-credit path must NOT — crediting yield adds fully-backed collateral (1:1), so it can only pull CR toward 100% and can never make the protocol under-backed. Gating it on the mint floor would make yield undistributable whenever CR sits at the floor (the natural equilibrium), so yield crediting uses a 100% fully-backed floor.

Notes:

  • security: Reverts the caller if the projected CR would fall below minRatio

  • validation: Reverts on zero projected backing requirement

  • state-changes: None - view function

  • events: None

  • errors: InsufficientCollateralization / InvalidAmount

  • reentrancy: Not applicable - view function

  • access: Internal

  • oracle: Consumes the supplied validated price; no direct oracle read

function _enforceProjectedCollateralizationFloor(
    uint256 netAmount,
    uint256 qeuroToMint,
    uint256 eurUsdPrice,
    uint256 minRatio
) internal view;

Parameters

NameTypeDescription
netAmountuint256Net USDC added by the operation (6 decimals)
qeuroToMintuint256QEURO to be minted by the operation (18 decimals)
eurUsdPriceuint256Live EUR/USD price used to value QEURO debt (18 decimals)
minRatiouint256Minimum acceptable projected CR (18-dec ratio, e.g. 105e18)

_mintQEUROCommit

Commits mint flow effects/interactions after validation phase

Called via explicit self-call from mintQEURO to separate validation and commit phases.

Notes:

  • security: Restricted by onlySelf; executed from nonReentrant parent flow

  • validation: Assumes caller already validated collateralization and oracle constraints

  • state-changes: Updates vault accounting, oracle cache timestamps, and optional Aave principal tracker

  • events: Emits QEUROminted and potentially downstream fee/yield events

  • errors: Token, hedger sync, fee routing, and Aave operations may revert

  • reentrancy: Structured CEI commit path called from guarded parent

  • access: External self-call entrypoint only

  • oracle: Uses pre-validated oracle price input

function _mintQEUROCommit(
    address payer,
    address qeuroRecipient,
    uint256 usdcAmount,
    uint256 fee,
    uint256 netAmount,
    uint256 qeuroToMint,
    uint256 eurUsdPrice,
    bool isValidPrice,
    uint256 targetVaultId
) external onlySelf;

Parameters

NameTypeDescription
payeraddressUser receiving freshly minted QEURO
qeuroRecipientaddressAddress receiving minted QEURO output.
usdcAmountuint256Gross USDC transferred in
feeuint256Protocol fee portion from usdcAmount
netAmountuint256Net USDC credited to collateral after fees
qeuroToMintuint256QEURO amount to mint for minter
eurUsdPriceuint256Validated EUR/USD price used for accounting cache
isValidPriceboolWhether oracle read used for cache timestamp was valid
targetVaultIduint256Target vault id for optional auto-deployment (0 disables deployment).

_autoDeployToVault

Internal function to auto-deploy USDC to Aave after minting

Uses strict CEI ordering and lets failures revert to preserve accounting integrity

Notes:

  • security: Updates accounting before external interaction to remove reentrancy windows

  • validation: Validates MockAaveVault is set and amount > 0

  • state-changes: Updates totalUsdcHeld and totalUsdcInAave before calling MockAaveVault

  • events: Emits UsdcDeployedToAave on success

  • errors: Reverts on failed deployment or invalid Aave return value

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _autoDeployToVault(uint256 vaultId, uint256 usdcAmount) internal;

Parameters

NameTypeDescription
vaultIduint256Target external vault id for deployment.
usdcAmountuint256Amount of USDC to deploy (6 decimals)

redeemQEURO

Redeems QEURO for USDC - automatically routes to normal or liquidation mode

Redeem process:

  1. Check if protocol is in liquidation mode (CR <= 101%)
  2. If liquidation mode: use pro-rata distribution based on actual USDC in vault
  • Payout = (qeuroAmount / totalSupply) * totalVaultUsdc
  • Hedger loses margin proportionally: (qeuroAmount / totalSupply) * hedgerMargin
  • Fees are always applied using redemptionFee
  1. If normal mode: use oracle price with standard fees
  2. Burn QEURO and transfer USDC

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits QEURORedeemed or LiquidationRedeemed based on mode

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: No access restrictions

  • oracle: Requires fresh oracle price data

  • security: No flash loan protection needed - legitimate redemption operation

function redeemQEURO(uint256 qeuroAmount, uint256 minUsdcOut) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to swap for USDC
minUsdcOutuint256Minimum amount of USDC expected

_dispatchRedeemCommit

Dispatches redeem commit through explicit self-call.

Preserves separation between validation/read phase and commit/interactions phase.

Notes:

  • security: Uses onlySelf-guarded commit entrypoint.

  • validation: Assumes payload was prepared by validated redeem flow.

  • state-changes: No direct state changes in dispatcher.

  • events: No direct events in dispatcher.

  • errors: Propagates commit-phase revert reasons.

  • reentrancy: Called from guarded parent flow.

  • access: Internal helper.

  • oracle: No direct oracle reads.

function _dispatchRedeemCommit(RedeemCommitPayload memory payload) internal;

Parameters

NameTypeDescription
payloadRedeemCommitPayloadPacked redeem commit payload.

_redeemQEUROCommit

Commits normal-mode redemption effects/interactions after validation

Called via explicit self-call from redeemQEURO.

Notes:

  • security: Restricted by onlySelf; called from nonReentrant parent flow

  • validation: Reverts if held liquidity is insufficient or mint tracker underflows

  • state-changes: Updates collateral/mint trackers and price cache

  • events: Emits QEURORedeemed and downstream fee routing events

  • errors: Reverts on insufficient balances, token failures, or downstream integration failures

  • reentrancy: CEI commit path invoked from guarded parent

  • access: External self-call entrypoint only

  • oracle: Uses pre-validated oracle price input

function _redeemQEUROCommit(
    address redeemer,
    uint256 qeuroAmount,
    uint256 usdcToReturn,
    uint256 netUsdcToReturn,
    uint256 fee,
    uint256 eurUsdPrice,
    bool isValidPrice,
    uint256 externalWithdrawalAmount
) external onlySelf;

Parameters

NameTypeDescription
redeemeraddressUser redeeming QEURO
qeuroAmountuint256QEURO amount burned from redeemer
usdcToReturnuint256Gross USDC redemption amount before fee transfer split
netUsdcToReturnuint256Net USDC transferred to the redeemer
feeuint256Protocol fee amount from redemption
eurUsdPriceuint256Validated EUR/USD price used for cache update
isValidPriceboolWhether oracle read used for cache timestamp was valid
externalWithdrawalAmountuint256Planned USDC amount to source from Aave (if needed)

_redeemLiquidationMode

Internal function for liquidation mode redemption (pro-rata based on actual USDC)

Internal function to handle QEURO redemption in liquidation mode (CR ≤ 101%)

Called by redeemQEURO when protocol is in liquidation mode (CR <= 101%)

Key formulas:

  • Payout = (qeuroAmount / totalSupply) * totalVaultUsdc (actual USDC, not market value)
  • Hedger loss = (qeuroAmount / totalSupply) * hedgerMargin (proportional margin reduction)
  • Fees applied using redemptionFee

Called by redeemQEURO when protocol enters liquidation mode Liquidation Mode Formulas:

  1. userPayout = (qeuroAmount / totalQEUROSupply) × totalVaultUSDC
  • Pro-rata distribution based on actual USDC, NOT fair value
  • If CR < 100%, users take a haircut
  • If CR > 100%, users receive a small premium
  1. hedgerLoss = (qeuroAmount / totalQEUROSupply) × hedgerMargin
  • Hedger absorbs proportional margin loss
  • Recorded via hedgerPool.recordLiquidationRedeem() In liquidation mode, hedger's unrealizedPnL = -margin (all margin at risk).

Notes:

  • security: Internal function - handles liquidation redemptions with pro-rata distribution

  • validation: Validates totalSupply > 0, oracle price valid, usdcPayout >= minUsdcOut, sufficient balance

  • state-changes: Reduces totalUsdcHeld, totalMinted, calls hedgerPool.recordLiquidationRedeem

  • events: Emits LiquidationRedeemed

  • errors: Reverts with InvalidAmount, InvalidOraclePrice, ExcessiveSlippage, InsufficientBalance

  • reentrancy: Protected by CEI pattern - state changes before external calls

  • access: Internal function - called by redeemQEURO

  • oracle: Requires valid EUR/USD price from oracle

function _redeemLiquidationMode(
    uint256 qeuroAmount,
    uint256 minUsdcOut,
    uint256 collateralizationRatioBps,
    uint256 eurUsdPrice,
    bool isValidPrice
) internal;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to redeem (18 decimals)
minUsdcOutuint256Minimum USDC expected (slippage protection)
collateralizationRatioBpsuint256Current CR in basis points (for event emission)
eurUsdPriceuint256Live, validated EUR/USD price routed in from redeemQEURO (18 decimals)
isValidPriceboolValidity flag for the routed oracle price, used for cache timestamping

_redeemLiquidationCommit

Commits liquidation-mode redemption effects/interactions

Called from _redeemLiquidationMode.

Notes:

  • security: Called from guarded liquidation flow

  • validation: Reverts on insufficient balances or mint tracker underflow

  • state-changes: Updates collateral/mint trackers and notifies hedger pool liquidation accounting

  • events: Emits LiquidationRedeemed and downstream fee routing events

  • errors: Reverts on balance/transfer/integration failures

  • reentrancy: CEI commit path invoked from nonReentrant parent

  • access: Internal helper

  • oracle: No direct oracle reads (uses precomputed inputs)

function _redeemLiquidationCommit(LiquidationCommitParams memory params) internal;

Parameters

NameTypeDescription
paramsLiquidationCommitParamsPacked liquidation commit values

_planExternalVaultWithdrawal

Calculates required Aave withdrawal to satisfy a USDC payout

Returns zero when vault-held USDC already covers requiredUsdc.

Notes:

  • security: Enforces that Aave vault is configured before planning an Aave-backed withdrawal

  • validation: Reverts with InsufficientBalance when deficit exists and Aave is not configured

  • state-changes: None

  • events: None

  • errors: Reverts with InsufficientBalance when no Aave source exists for deficit

  • reentrancy: No external calls

  • access: Internal helper

  • oracle: No oracle dependencies

function _planExternalVaultWithdrawal(uint256 requiredUsdc) internal view returns (uint256 vaultWithdrawalAmount);

Parameters

NameTypeDescription
requiredUsdcuint256Target USDC amount that must be available in vault balance

Returns

NameTypeDescription
vaultWithdrawalAmountuint256Additional USDC that should be sourced from Aave

_calculateLiquidationFees

Calculates liquidation fees from gross liquidation payout.

Fees are always applied in liquidation mode: fee = usdcPayout * redemptionFee / 1e18.

Notes:

  • security: View only

  • validation: Uses current redemptionFee in 1e18 precision

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: None

  • access: Internal

  • oracle: None

function _calculateLiquidationFees(uint256 usdcPayout) internal view returns (uint256 fee, uint256 netPayout);

Parameters

NameTypeDescription
usdcPayoutuint256Gross payout amount

Returns

NameTypeDescription
feeuint256Fee amount
netPayoutuint256Net payout after fees

_notifyHedgerPoolLiquidation

Notifies hedger pool of liquidation redemption for margin adjustment.

When hedger collateral exists, this call is atomic and must succeed. It is skipped only when HedgerPool is unset or has zero collateral.

Notes:

  • security: Reverts liquidation flow if HedgerPool call fails while collateral exists

  • validation: Skips only when HedgerPool is zero or totalMargin is 0

  • state-changes: HedgerPool state via recordLiquidationRedeem

  • events: Via HedgerPool

  • errors: Bubbles HedgerPool errors in atomic path

  • reentrancy: External call to HedgerPool

  • access: Internal

  • oracle: None

function _notifyHedgerPoolLiquidation(uint256 qeuroAmount, uint256 totalSupply) internal;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO being redeemed
totalSupplyuint256Total QEURO supply for pro-rata calculation

_transferLiquidationFees

Transfers liquidation fees to fee collector if applicable

Approves USDC to FeeCollector and calls collectFees; no-op if fees disabled or fee is 0

Notes:

  • security: Requires approve and collectFees to succeed

  • validation: fee > 0

  • state-changes: USDC balance of feeCollector

  • events: Via FeeCollector

  • errors: TokenTransferFailed if approve fails

  • reentrancy: External call to FeeCollector

  • access: Internal

  • oracle: None

function _transferLiquidationFees(uint256 fee) internal;

Parameters

NameTypeDescription
feeuint256Fee amount to transfer

isProtocolCollateralized

Retrieves the vault's global metrics

Checks if the protocol is properly collateralized by hedgers

Returns comprehensive vault metrics for monitoring and analytics

Public view function to check collateralization status

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check collateralization status

  • oracle: No oracle dependencies

function isProtocolCollateralized() external view returns (bool isCollateralized, uint256 totalMargin);

Returns

NameTypeDescription
isCollateralizedboolTrue if protocol has active hedging positions
totalMarginuint256Total margin in HedgerPool (0 if not set)

updateParameters

Updates the vault parameters (governance only)

Safety constraints:

  • Fees <= 5% (user protection)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateParameters(uint256 _mintFee, uint256 _redemptionFee) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_mintFeeuint256New minting fee (1e18 precision, 1e18 = 100%)
_redemptionFeeuint256New redemption fee (1e18 precision, 1e18 = 100%)

updateHedgerRewardFeeSplit

Updates the fee share routed to HedgerPool reward reserve.

Governance-controlled split applied in _routeProtocolFees.

Notes:

  • security: Restricted to governance and bounded by max split constant.

  • validation: Reverts when newSplit exceeds MAX_HEDGER_REWARD_FEE_SPLIT.

  • state-changes: Updates hedgerRewardFeeSplit.

  • events: Emits HedgerRewardFeeSplitUpdated.

  • errors: Reverts with ConfigValueTooHigh on invalid split.

  • reentrancy: Not applicable - simple state update.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle interaction.

function updateHedgerRewardFeeSplit(uint256 newSplit) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newSplituint256Share in 1e18 precision (1e18 = 100%).

updateCollateralizationThresholds

Updates the collateralization thresholds (governance only)

Safety constraints:

  • minCollateralizationRatioForMinting >= 101000000000000000000 (101.000000% minimum = 101 * 1e18)
  • criticalCollateralizationRatio <= minCollateralizationRatioForMinting
  • criticalCollateralizationRatio >= 100000000000000000000 (100.000000% minimum = 100 * 1e18)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateCollateralizationThresholds(
    uint256 _minCollateralizationRatioForMinting,
    uint256 _criticalCollateralizationRatio
) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_minCollateralizationRatioForMintinguint256New minimum collateralization ratio for minting (in 18 decimals)
_criticalCollateralizationRatiouint256New critical collateralization ratio for liquidation (in 18 decimals)

updateOracle

Updates the oracle address

Updates the oracle contract address for price feeds

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Reverts if the new oracle is the zero address

  • state-changes: Updates the oracle address

  • events: Emits OracleUpdated(oldOracle, newOracle)

  • errors: Throws InvalidOracle if the new oracle is the zero address

  • reentrancy: Not protected - single state write, no external calls

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: Sets the oracle address; does not read price data

function updateOracle(address _oracle) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_oracleaddressNew oracle address

updateHedgerPool

Updates the HedgerPool address

Updates the HedgerPool contract address for collateralization checks

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateHedgerPool(address _hedgerPool) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_hedgerPooladdressNew HedgerPool address

updateUserPool

Updates the UserPool address

Updates the UserPool contract address for user deposit tracking

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateUserPool(address _userPool) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_userPooladdressNew UserPool address

updateFeeCollector

Updates the fee collector address

Only governance role can update the fee collector address

Notes:

  • security: Validates address is not zero before updating

  • validation: Ensures _feeCollector is not address(0)

  • state-changes: Updates feeCollector state variable

  • events: No events emitted

  • errors: Reverts if _feeCollector is address(0)

  • reentrancy: No reentrancy risk, simple state update

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateFeeCollector(address _feeCollector) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_feeCollectoraddressNew fee collector address

setStakingVault

Configures adapter and activation status for a vault id.

Governance management entrypoint for external staking vault routing.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on zero vault id or zero adapter address.

  • state-changes: Updates adapter mapping and active-status mapping for vaultId.

  • events: Emits StakingVaultConfigured.

  • errors: Reverts with InvalidVault or ZeroAddress.

  • reentrancy: No reentrancy-sensitive external calls.

  • access: Governance-only.

  • oracle: No oracle dependencies.

function setStakingVault(uint256 vaultId, address adapter, bool active) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
vaultIduint256Vault id to configure.
adapteraddressAdapter contract implementing IExternalStakingVault.
activeboolActivation flag controlling whether vault id is eligible for routing.

realizeExternalLoss

Records a loss of externally deployed principal.

The loss is socialised through the vault collateral account; hedger margin is untouched and the existing collateralization/liquidation rules apply.

Notes:

  • security: Governance-only accounting correction.

  • validation: Requires a configured adapter and a lower reported underlying value.

  • state-changes: Reduces tracked external principal and aggregate external collateral.

  • events: Emits ExternalVaultLossRealized.

  • errors: InvalidVault, ZeroAddress, or InvalidCondition.

  • reentrancy: Adapter read is view-only.

  • access: Governance role.

  • oracle: No oracle dependency.

function realizeExternalLoss(uint256 vaultId) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
vaultIduint256External vault identifier.

setDefaultStakingVaultId

Sets default vault id used for mint routing and fallback redemption priority.

vaultId == 0 clears default routing.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Non-zero ids must be active and have a configured adapter.

  • state-changes: Updates defaultStakingVaultId.

  • events: Emits DefaultStakingVaultUpdated.

  • errors: Reverts with InvalidVault/ZeroAddress for invalid non-zero ids.

  • reentrancy: No reentrancy-sensitive external calls.

  • access: Governance-only.

  • oracle: No oracle dependencies.

function setDefaultStakingVaultId(uint256 vaultId) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
vaultIduint256New default vault id (or 0 to clear).

setRedemptionPriority

Sets ordered vault ids used when sourcing redemption liquidity from external vaults.

Replaces the full priority array with provided values.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Each id must be non-zero, active, and mapped to a configured adapter.

  • state-changes: Replaces redemptionPriorityVaultIds.

  • events: Emits RedemptionPriorityUpdated.

  • errors: Reverts with InvalidVault/ZeroAddress on invalid entries.

  • reentrancy: No reentrancy-sensitive external calls.

  • access: Governance-only.

  • oracle: No oracle dependencies.

function setRedemptionPriority(uint256[] calldata vaultIds) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
vaultIdsuint256[]Ordered vault ids to use for redemption withdrawals.

selfRegisterStQEURO

Registers this vault in stQEUROFactory using strict self-call semantics.

Previews deterministic token address, binds local state, then executes factory registration and verifies match.

Notes:

  • security: Restricted to governance and protected by nonReentrant.

  • validation: Requires non-zero factory address, non-zero vault id, and uninitialized local stQEURO state.

  • state-changes: Sets stQEUROFactory, stQEUROToken, and stQEUROVaultId for this vault.

  • events: Emits StQEURORegistered after successful factory registration.

  • errors: Reverts on invalid inputs, duplicate initialization, or mismatched preview/registered token address.

  • reentrancy: Guarded by nonReentrant; state binding follows CEI before external registration call.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function selfRegisterStQEURO(address factory, uint256 vaultId, string calldata vaultName)
    external
    onlyRole(GOVERNANCE_ROLE)
    nonReentrant
    returns (address token);

Parameters

NameTypeDescription
factoryaddressAddress of stQEUROFactory.
vaultIduint256Desired vault id in the factory registry.
vaultNamestringUppercase alphanumeric vault name.

Returns

NameTypeDescription
tokenaddressNewly deployed stQEURO token address.

creditVaultYield

Credits harvested user yield into a specific stQEURO vault as real QEURO backing.

Converts harvested user-side USDC into newly minted QEURO sent directly to the target stQEURO vault. No protocol yield fee applies; configured execution costs are paid from the yield.

Notes:

  • security: Restricted to YIELD_DISTRIBUTOR_ROLE; validates oracle, collateralization, and vault bindings.

  • validation: Reverts on zero amounts, invalid vault ids, invalid prices, or unsafe collateralization.

  • state-changes: Updates price cache metadata, protocol USDC/QEURO accounting, and hedger synchronization state.

  • events: Emits no direct event; downstream token mint/transfer events provide observability.

  • errors: Reverts on invalid inputs, failed transfers, unsafe mint conditions, or hedger sync failure.

  • reentrancy: Guarded by nonReentrant.

  • access: Restricted to addresses with YIELD_DISTRIBUTOR_ROLE.

  • oracle: Requires validated EUR/USD and fresh execution depth/capacity when pricing is enabled.

function creditVaultYield(uint256 vaultId, uint256 usdcAmount)
    external
    nonReentrant
    whenNotPaused
    onlyRole(YIELD_DISTRIBUTOR_ROLE)
    returns (uint256 qeuroMinted);

Parameters

NameTypeDescription
vaultIduint256Vault identifier whose stQEURO series receives the compounded yield.
usdcAmountuint256Amount of harvested USDC allocated to users for this vault.

Returns

NameTypeDescription
qeuroMinteduint256Net QEURO minted into the stQEURO vault.

_creditVaultYield

Credits already-held USDC into an stQEURO vault as freshly minted QEURO backing.

Shared core used by creditVaultYield (after pulling USDC from the caller) and by harvestAndDistributeVaultYield (after realizing adapter yield into this contract). Assumes usdcAmount USDC is already held by this contract; performs no transfer-in. Reserves execution exposure before minting and excludes execution costs from reference backing.

Notes:

  • security: Caller must enforce access control, pause, and reentrancy guards.

  • validation: Reverts on invalid vault ids, empty share supply, invalid prices, or unsafe collateralization.

  • state-changes: Updates price cache, totalUsdcHeld, totalMinted, hedger sync, and mints QEURO to the stQEURO vault.

  • events: Emits no direct event; downstream token mint/transfer events provide observability.

  • errors: Reverts on invalid inputs, failed transfers, unsafe mint conditions, or hedger sync failure.

  • reentrancy: Must be invoked from a nonReentrant external entrypoint.

  • access: Internal.

  • oracle: Requires validated EUR/USD and fresh execution depth/capacity when pricing is enabled.

function _creditVaultYield(uint256 vaultId, uint256 usdcAmount) internal returns (uint256 qeuroMinted);

Parameters

NameTypeDescription
vaultIduint256Vault identifier whose stQEURO series receives the compounded yield.
usdcAmountuint256Amount of already-held USDC to convert into stQEURO backing.

Returns

NameTypeDescription
qeuroMinteduint256Net QEURO minted into the stQEURO vault.

setFundingRateAnnualBps

Retired annual-funding setter retained for selector compatibility.

Always reverts; use setHedgerStakingYieldHaircutBps for the new percentage-of-yield policy.

Notes:

  • security: Existing governance restriction remains.

  • validation: This setting is no longer supported.

  • state-changes: None.

  • events: None.

  • errors: InvalidCondition or access-control failure.

  • reentrancy: No external calls.

  • access: GOVERNANCE_ROLE.

  • oracle: None.

function setFundingRateAnnualBps(uint256 newRateBps) external view onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newRateBpsuint256Unused legacy annual funding input.

setHedgerYieldRecipient

Sets the recipient of the staking yield haircut.

Nonzero hedger payouts require this recipient to be configured.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on the zero address.

  • state-changes: Updates hedgerYieldRecipient.

  • events: Emits HedgerYieldRecipientUpdated.

  • errors: Reverts with ZeroAddress for an invalid recipient.

  • reentrancy: No reentrancy-sensitive external calls.

  • access: Governance-only.

  • oracle: No oracle dependencies.

function setHedgerYieldRecipient(address newRecipient) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newRecipientaddressNew hedger yield recipient address.

harvestAndDistributeVaultYield

Harvests yield and allocates it by the staking ratio, with a haircut on gross staking yield.

The linked library snapshots ownership, realizes yield, routes USDC and records the keeper timestamp. The existing credit path converts the post-haircut staker allocation into QEURO. Allocation, execution admission and minting are one atomic operation.

Notes:

  • security: Restricted to YIELD_DISTRIBUTOR_ROLE; protected by nonReentrant and pause.

  • validation: Reverts when vault id is invalid/inactive or adapter is unset.

  • state-changes: Updates the keeper harvest timestamp, protocol USDC/QEURO accounting, and stQEURO backing; moves USDC to the hedger recipient and treasury.

  • events: Emits VaultYieldDistributed.

  • errors: Reverts on invalid configuration, adapter failures, or unsafe credit conditions.

  • reentrancy: Guarded by nonReentrant.

  • access: Restricted to YIELD_DISTRIBUTOR_ROLE.

  • oracle: Requires a fresh validated EUR/USD reference price.

function harvestAndDistributeVaultYield(uint256 vaultId)
    external
    nonReentrant
    whenNotPaused
    onlyRole(YIELD_DISTRIBUTOR_ROLE);

Parameters

NameTypeDescription
vaultIduint256Vault id whose adapter yield is harvested and distributed.

previewVaultYieldDistribution

Preview USDC distribution using the harvest-time staking ratio; call with eth_call.

Non-view for ABI compatibility. No USDC is transferred.

Notes:

  • security: Uses the same calculation and guards as harvest.

  • validation: Active single funded strategy required. Conversion checks are separate.

  • state-changes: None.

  • events: None.

  • errors: Propagates library validation errors.

  • reentrancy: nonReentrant.

  • access: Public.

  • oracle: Fresh validated EUR/USD price.

function previewVaultYieldDistribution(uint256 vaultId)
    external
    nonReentrant
    returns (StakingYieldLibrary.Split memory split);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
splitStakingYieldLibrary.SplitEstimated allocations before execution costs.

setHedgerStakingYieldHaircutBps

Configure the hedger percentage of gross earned staking yield (0 to 100%).

The only configurable deduction from harvested staking yield; never deducts principal.

Notes:

  • security: Governance only.

  • validation: At most 10,000 bps.

  • state-changes: Updates haircut setting.

  • events: HedgerStakingYieldHaircutUpdated.

  • errors: AboveLimit or access-control failure.

  • reentrancy: No external calls.

  • access: GOVERNANCE_ROLE.

  • oracle: None.

function setHedgerStakingYieldHaircutBps(uint256 newBps) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newBpsuint256Basis points, where 200 means 2% of earned yield.

yieldDistributionConfig

Read staking-yield distribution settings and the keeper's last-harvest timestamp.

Available from version 1.4.0; the retired annual funding rate is not returned here.

Notes:

  • security: Read-only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: View only.

  • access: Public.

  • oracle: None.

function yieldDistributionConfig(uint256 vaultId)
    external
    view
    returns (uint256 haircutBps, address hedgerRecipient, uint256 lastHarvest);

Parameters

NameTypeDescription
vaultIduint256Strategy identifier.

Returns

NameTypeDescription
haircutBpsuint256Percentage of earned staking yield in basis points.
hedgerRecipientaddressConfigured USDC recipient.
lastHarvestuint256Last successful harvest timestamp.

harvestConfig

Returns the yield-distribution configuration for a vault id.

Single read replacing the per-field getters to keep the contract under the EIP-170 limit.

Notes:

  • security: Read-only helper.

  • validation: No input validation required.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function harvestConfig(uint256 vaultId)
    external
    view
    returns (uint256 fundingRateBps, address hedgerRecipient, uint256 lastHarvest);

Parameters

NameTypeDescription
vaultIduint256Vault id to query.

Returns

NameTypeDescription
fundingRateBpsuint256Always zero: annual funding is retired.
hedgerRecipientaddressConfigured hedger recipient; zero is not a treasury fallback.
lastHarvestuint256Timestamp of the last harvest+distribute for the vault id.

deployUsdcToVault

Deploys held USDC principal into a configured external vault adapter.

Operator flow for moving idle vault USDC into yield-bearing adapters.

Notes:

  • security: Restricted to VAULT_OPERATOR_ROLE; protected by nonReentrant.

  • validation: Reverts on zero amount, insufficient held liquidity, invalid vault id, or unset adapter.

  • state-changes: Decreases totalUsdcHeld, increases per-vault and global external principal trackers.

  • events: Emits UsdcDeployedToExternalVault.

  • errors: Reverts on invalid inputs, accounting constraints, or adapter failures.

  • reentrancy: Guarded by nonReentrant.

  • access: Vault-operator role.

  • oracle: No direct oracle dependency.

function deployUsdcToVault(uint256 vaultId, uint256 usdcAmount)
    external
    nonReentrant
    onlyRole(VAULT_OPERATOR_ROLE);

Parameters

NameTypeDescription
vaultIduint256Target vault id.
usdcAmountuint256USDC amount to deploy (6 decimals).

getVaultExposure

Returns current exposure snapshot for a vault id.

Provides adapter address, active flag, tracked principal, and the adapter underlying read.

Notes:

  • security: Read-only helper.

  • validation: No additional validation; unknown ids return zeroed/default values.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Propagates a reverting adapter totalUnderlying() read (fail-closed).

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultExposure(uint256 vaultId)
    external
    view
    returns (address adapter, bool active, uint256 principalTracked, uint256 currentUnderlying);

Parameters

NameTypeDescription
vaultIduint256Vault id to query.

Returns

NameTypeDescription
adapteraddressAdapter address mapped to vault id.
activeboolWhether vault id is active.
principalTrackeduint256Principal tracked locally for vault id.
currentUnderlyinguint256Current underlying balance from the adapter (0 when no adapter set).

_withdrawUsdcFromExternalVaults

Withdraws requested USDC from external vault adapters following priority ordering.

Iterates resolved priority list until amount is fully satisfied or reverts on shortfall.

Notes:

  • security: Internal liquidity-sourcing helper for guarded redeem flows.

  • validation: Reverts with InsufficientBalance if aggregate withdrawals cannot satisfy request.

  • state-changes: Updates per-vault and global principal trackers via delegated withdrawal helper.

  • events: Emits per-vault withdrawal events from delegated helper.

  • errors: Reverts on insufficient liquidity or adapter withdrawal mismatch.

  • reentrancy: Internal helper; downstream adapter calls are performed in controlled flow.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _withdrawUsdcFromExternalVaults(uint256 usdcAmount) internal returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
usdcAmountuint256Total USDC amount to source from external vaults.

Returns

NameTypeDescription
usdcWithdrawnuint256Total USDC withdrawn from adapters.

_resolveWithdrawalPriority

Resolves external-vault withdrawal priority list.

Uses explicit redemptionPriorityVaultIds when configured, otherwise falls back to default vault id.

Notes:

  • security: Internal read helper.

  • validation: Reverts if neither explicit priority nor default vault is available.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with InsufficientBalance when no usable routing exists.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _resolveWithdrawalPriority() internal view returns (uint256[] memory priority);

Returns

NameTypeDescription
priorityuint256[]Ordered vault ids to use for withdrawal sourcing.

withdrawProtocolFees

Withdraws accumulated protocol fees

Fees accumulate during minting and redemptions

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function withdrawProtocolFees(address to) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
toaddressDestination address for the fees

addHedgerDeposit

Adds hedger USDC deposit to vault's total USDC reserves

Called by HedgerPool when hedgers open positions to unify USDC liquidity

Notes:

  • security: Validates caller is HedgerPool contract and amount is positive

  • validation: Validates amount > 0 and caller is authorized HedgerPool

  • state-changes: Updates totalUsdcHeld with hedger deposit amount

  • events: Emits HedgerDepositAdded with deposit details

  • errors: Throws "Vault: Only HedgerPool can call" if caller is not HedgerPool

  • errors: Throws "Vault: Amount must be positive" if amount is zero

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to HedgerPool contract only

  • oracle: No oracle dependencies

function addHedgerDeposit(uint256 usdcAmount) external nonReentrant;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC deposited by hedger (6 decimals)

withdrawHedgerDeposit

Withdraws hedger USDC deposit from vault's reserves

Called by HedgerPool when hedgers close positions to return their deposits

Notes:

  • security: Validates caller is HedgerPool, amount is positive, and sufficient reserves

  • validation: Validates amount > 0, caller is authorized, and totalUsdcHeld >= amount

  • state-changes: Updates totalUsdcHeld and transfers USDC to hedger

  • events: Emits HedgerDepositWithdrawn with withdrawal details

  • errors: Throws "Vault: Only HedgerPool can call" if caller is not HedgerPool

  • errors: Throws "Vault: Amount must be positive" if amount is zero

  • errors: Throws "Vault: Insufficient USDC reserves" if not enough USDC available

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to HedgerPool contract only

  • oracle: No oracle dependencies

function withdrawHedgerDeposit(address hedger, uint256 usdcAmount) external nonReentrant;

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger receiving the USDC
usdcAmountuint256Amount of USDC to withdraw (6 decimals)

getTotalUsdcAvailable

Gets the total USDC available (vault + Aave)

Returns total USDC that can be used for withdrawals/redemptions

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public access - anyone can query total USDC available

  • oracle: No oracle dependencies

function getTotalUsdcAvailable() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total USDC available (vault + Aave) (6 decimals)

updatePriceCache

Refreshes the deviation-baseline price cache to the current valid oracle price

PERMISSIONLESS. The cache baseline only ever advances to a price the oracle itself reports as valid (this reverts on !isValid), so anyone (e.g. a keeper) can re-baseline during a sharp EUR move to clear the vault's 2% deviation guard and restore mint/redeem availability without waiting on a governance multisig. It cannot commit a manipulated or stale price — the oracle's own bounds / staleness / circuit-breaker checks gate validity. Tradeoff: this removes the governance-in-the-loop pause on the vault's SECONDARY deviation circuit; the oracle adapter's validity remains the primary protection layer.

Notes:

  • security: Permissionless; only commits an oracle-validated price; nonReentrant.

  • validation: Validates oracle price is valid before updating cache

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateBlock, and lastPriceUpdateTime

  • events: Emits PriceCacheUpdated event

  • errors: Reverts if oracle price is invalid

  • reentrancy: Protected by nonReentrant

  • access: Public - callable by anyone

  • oracle: Requires valid oracle price

function updatePriceCache() external nonReentrant;

_applyPriceCacheUpdate

Applies a validated price cache update

Commit-phase helper called via explicit self-call from updatePriceCache.

Notes:

  • security: Restricted by onlySelf

  • validation: Assumes caller already validated oracle output

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateBlock, and lastPriceUpdateTime

  • events: Emits PriceCacheUpdated

  • errors: None

  • reentrancy: No external calls

  • access: External self-call entrypoint only

  • oracle: No direct oracle reads (uses pre-validated input)

function _applyPriceCacheUpdate(uint256 oldPrice, uint256 eurUsdPrice) external onlySelf;

Parameters

NameTypeDescription
oldPriceuint256Previous cached EUR/USD price
eurUsdPriceuint256New validated EUR/USD price

_commitPriceCache

Commits the validated EUR/USD price-cache fields used for flash-loan/deviation protection.

Consolidates the repeated cache-write pattern shared by the mint, redeem, liquidation, and yield-crediting commit paths plus the governance cache setters. Refreshes the timestamp only when the supplied price is valid (commit/governance callers pass true for already-validated prices). Replaces the former _updatePriceTimestamp helper.

Notes:

  • security: Writes only price-cache bookkeeping fields; callers enforce price validation.

  • validation: Assumes the caller already validated the supplied price.

  • state-changes: Updates lastPriceUpdateBlock, lastValidEurUsdPrice, and (if valid) lastPriceUpdateTime.

  • events: No events emitted.

  • errors: No errors thrown.

  • reentrancy: Not protected - internal function only.

  • access: Internal function - no access restrictions.

  • oracle: No oracle dependencies.

function _commitPriceCache(uint256 eurUsdPrice, bool isValidPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Validated EUR/USD price to cache (18 decimals).
isValidPriceboolWhether the price is valid; when true, refreshes lastPriceUpdateTime.

_getExternalVaultCollateralBalance

Computes aggregate external-vault collateral, valued loss-aware per position.

Sums min(principalUsdcByVaultId[id], adapter.totalUnderlying()) over the redemption set (see _externalVaultCollateral). Fails closed on an adapter read failure.

Notes:

  • security: Internal read helper; performs staticcalls to configured adapters.

  • validation: Per-position value is capped at the live adapter underlying.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Propagates a reverting adapter totalUnderlying() read (fail-closed).

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _getExternalVaultCollateralBalance() internal view returns (uint256 externalCollateral);

Returns

NameTypeDescription
externalCollateraluint256Total external collateral balance in USDC units.

_externalVaultCollateral

Loss-aware USDC value of one external vault position: min(principal, adapterUnderlying).

The principal cap keeps unharvested yield out of redemption backing; the underlying cap reflects an ERC-4626 share-price loss immediately. Shares the adapter read with getVaultExposure via _adapterUnderlying.

Notes:

  • security: Read-only helper; performs a staticcall to the adapter.

  • validation: Returns 0 for a zero-principal vault.

  • state-changes: None.

  • events: None.

  • errors: Propagates a reverting adapter totalUnderlying() read (fail-closed).

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _externalVaultCollateral(uint256 vaultId) internal view returns (uint256 value);

Parameters

NameTypeDescription
vaultIduint256External staking vault id.

Returns

NameTypeDescription
valueuint256Loss-aware collateral contribution for the vault id, in USDC (6 decimals).

_adapterUnderlying

Reads an adapter's live totalUnderlying(), or 0 when no adapter is configured.

Shared by _externalVaultCollateral (collateral accounting) and getVaultExposure (reporting) so the adapter read exists once. Intentionally NOT wrapped in try/catch: a failed read fails closed rather than masking a loss as intact principal. Standard ERC-4626 adapters do not revert on this view.

Notes:

  • security: Read-only helper; performs a staticcall to the adapter.

  • validation: Returns 0 when the adapter is unset.

  • state-changes: None.

  • events: None.

  • errors: Propagates a reverting adapter totalUnderlying() read (fail-closed).

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _adapterUnderlying(IExternalStakingVault adapter) internal view returns (uint256 underlying);

Parameters

NameTypeDescription
adapterIExternalStakingVaultExternal staking vault adapter (may be the zero adapter).

Returns

NameTypeDescription
underlyinguint256Adapter underlying USDC value, or 0 when the adapter is unset.

_isInRedemptionSet

Returns whether a vault id belongs to the redemption set used for collateral counting.

Mirrors EXACTLY the membership notion of _getExternalVaultCollateralBalance and _resolveWithdrawalPriority: a vault is in the set iff it appears in redemptionPriorityVaultIds, or (when that list is empty) it is the non-zero defaultStakingVaultId. Deployment is gated on this so principal can only ever land in a vault that is both counted as collateral and reachable by the withdrawal path.

Notes:

  • security: Internal read helper.

  • validation: No input validation.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _isInRedemptionSet(uint256 vaultId) internal view returns (bool inSet);

Parameters

NameTypeDescription
vaultIduint256Vault id to test.

Returns

NameTypeDescription
inSetboolTrue when the vault id is counted/withdrawable.

_requireInRedemptionSet

Reverts unless the vault id is in the redemption set (counted + withdrawable).

Used to gate external-vault deployment so collateral counting, withdrawal capacity, and deployed principal stay in lockstep. A vault that is active but absent from the redemption priority/default set would otherwise hold principal that is excluded from collateral and unreachable by the withdrawal path, stranding funds in liquidation.

Notes:

  • security: Internal guard.

  • validation: Reverts with InvalidVault when the vault id is outside the redemption set.

  • state-changes: None.

  • events: None.

  • errors: Reverts with CommonErrorLibrary.InvalidVault.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _requireInRedemptionSet(uint256 vaultId) internal view;

Parameters

NameTypeDescription
vaultIduint256Vault id being deployed to.

_getTotalCollateralWithAccruedYield

Returns total principal-backed collateral (held USDC + tracked external principal).

Sum of totalUsdcHeld and _getExternalVaultCollateralBalance(). Despite the legacy name, this intentionally EXCLUDES unharvested external-vault yield: the value equals what redemption/withdrawal can actually source, so collateral counting and withdrawal capacity stay consistent. Harvested yield is routed to stQEURO holders.

Notes:

  • security: Internal read helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Propagates unexpected view-read errors.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No direct oracle dependency.

function _getTotalCollateralWithAccruedYield() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total collateral in USDC units.

_routeProtocolFees

Routes protocol fees between HedgerPool reserve and FeeCollector at source.

Splits fee flow using hedgerRewardFeeSplit and transfers shares to each destination.

Notes:

  • security: Validates required dependency addresses before routing each share.

  • validation: No-op when fee == 0; reverts on unset required destinations.

  • state-changes: Increases allowances and forwards fee shares to HedgerPool/FeeCollector.

  • events: Emits ProtocolFeeRouted.

  • errors: Reverts when HedgerPool/FeeCollector dependencies are unset for non-zero shares.

  • reentrancy: Internal function; external calls are to configured protocol dependencies.

  • access: Internal helper.

  • oracle: No oracle interaction.

function _routeProtocolFees(uint256 fee, string memory sourceType) internal;

Parameters

NameTypeDescription
feeuint256Total fee amount in USDC (6 decimals).
sourceTypestringSource tag passed through to FeeCollector accounting.

getProtocolCollateralizationRatio

Calculates the current protocol collateralization ratio.

Formula: CR = (TotalCollateral / BackingRequirement) * 1e20 Where:

  • TotalCollateral = totalUsdcHeld + currentAaveCollateral (includes accrued Aave yield when available)
  • BackingRequirement = QEUROSupply * cachedEurUsdPrice / 1e30 (USDC value of outstanding debt) Returns ratio in 18-decimal percentage format:
  • 100% = 1e20
  • 101% = 1.01e20

Notes:

  • security: View function using cached price and current collateral state

  • validation: Returns 0 if pools are unset, supply is 0, or price cache is uninitialized

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check collateralization ratio

  • oracle: Uses cached oracle price (lastValidEurUsdPrice)

function getProtocolCollateralizationRatio() public view returns (uint256 ratio);

Returns

NameTypeDescription
ratiouint256Current collateralization ratio in 18-decimal percentage format

_getProtocolCollateralizationRatioAtPrice

Calculates protocol collateralization ratio using a supplied EUR/USD price.

Used by redemption routing so the liquidation decision and payout share one validated price.

Notes:

  • security: Internal helper using caller-supplied validated oracle price.

  • validation: Returns 0 if pools are unset, supply is 0, price is 0, or backing is 0.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - view function.

  • access: Internal.

  • oracle: Uses supplied oracle price.

function _getProtocolCollateralizationRatioAtPrice(uint256 eurUsdPrice) internal view returns (uint256 ratio);

Parameters

NameTypeDescription
eurUsdPriceuint256EUR/USD price to value QEURO debt, in 18 decimals.

Returns

NameTypeDescription
ratiouint256Collateralization ratio in 18-decimal percentage format.

canMint

Checks if minting is allowed based on the CACHED collateralization ratio

ADVISORY / OBSERVABILITY ONLY. Evaluates the mint gate against the cached EUR/USD price (lastValidEurUsdPrice), which can lag the live oracle price by up to the configured 2% deviation guard. The BINDING mint decision is enforced inside the mint flow via _enforceMintEligibility(eurUsdPrice) using the live oracle price, so off-chain callers of this view may briefly disagree with whether a mint would actually succeed.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes - view function

  • events: No events emitted - view function

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check minting status

  • oracle: Uses cached oracle price (lastValidEurUsdPrice)

function canMint() public view returns (bool);

Returns

NameTypeDescription
<none>boolcanMint Whether minting is currently allowed at the cached price

_canMintAtPrice

Evaluates mint eligibility using a supplied EUR/USD price.

Shared by the cached canMint() view and the live-price binding gate _enforceMintEligibility. The lastValidEurUsdPrice == 0 guard enforces the invariant that the price cache is bootstrapped before any mint, independent of which price values the collateralization ratio.

Notes:

  • security: Internal helper using caller-supplied price.

  • validation: Requires bootstrapped cache, active hedger, and either dust-only supply or CR >= mint threshold.

  • state-changes: None.

  • events: None.

  • errors: None - returns boolean flag.

  • reentrancy: Not applicable - view function.

  • access: Internal.

  • oracle: Uses supplied oracle price.

function _canMintAtPrice(uint256 eurUsdPrice) internal view returns (bool allowed);

Parameters

NameTypeDescription
eurUsdPriceuint256EUR/USD price used to value QEURO debt for the CR check (18 decimals).

Returns

NameTypeDescription
allowedboolWhether minting is permitted at the supplied price.

initializePriceCache

Pure view variant of getProtocolCollateralizationRatio using cached oracle price.

Seeds the oracle price cache so minting checks have a baseline.

Delegates to getProtocolCollateralizationRatio() and performs no state refresh.

Governance MUST call this once immediately after deployment, before any user mints. Uses an explicit bootstrap price to avoid external oracle interaction in this state-changing call.

Notes:

  • security: View-only wrapper.

  • validation: Inherits validation/fallback behavior from delegated function.

  • state-changes: None - view function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - view function.

  • access: Public.

  • oracle: Uses cached oracle price.

  • security: Restricted to governance.

  • validation: Requires initialEurUsdPrice > 0.

  • state-changes: Sets lastValidEurUsdPrice, lastPriceUpdateBlock, and lastPriceUpdateTime.

  • events: Emits PriceCacheUpdated.

  • errors: Reverts when price is zero or cache is already initialized.

  • reentrancy: Not applicable - no external callbacks.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Bootstrap input should come from governance/oracle process.

function initializePriceCache(uint256 initialEurUsdPrice) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
initialEurUsdPriceuint256Initial EUR/USD price in 18 decimals.

shouldTriggerLiquidation

Checks if liquidation should be triggered based on the CACHED collateralization ratio

ADVISORY / OBSERVABILITY ONLY. Evaluates against the cached EUR/USD price (lastValidEurUsdPrice), which can lag the live oracle price by up to the configured 2% deviation guard, so this may briefly disagree with live redemption routing near the threshold. The authoritative liquidation decision is made inside redeemQEURO using the live oracle price; for an authoritative live check use shouldTriggerLiquidationLive(). Mirrors redeemQEURO routing semantics: true only when 0 < CR <= criticalCollateralizationRatio (a zero ratio means uninitialized/empty protocol, which is not a liquidation state).

Notes:

  • security: View function - no state changes

  • validation: No input validation required - safe view function

  • state-changes: No state changes - view function

  • events: No events emitted - view function

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check liquidation status

  • oracle: Uses cached oracle price (lastValidEurUsdPrice)

function shouldTriggerLiquidation() public view returns (bool shouldLiquidate);

Returns

NameTypeDescription
shouldLiquidateboolWhether liquidation should be triggered at the cached price

shouldTriggerLiquidationLive

Authoritative live-price check for whether the protocol is in liquidation territory.

Reads the live EUR/USD price from the oracle and applies the same routing decision used by redeemQEURO (0 < CR <= criticalCollateralizationRatio). Non-view because the oracle EUR/USD getter is non-view at the IOracle interface level; off-chain consumers should call via eth_call/staticCall (no protocol state is mutated by this function).

Notes:

  • security: Read-only intent; performs no protocol state changes.

  • validation: Reverts if the oracle EUR/USD price is invalid.

  • state-changes: None in this contract.

  • events: No events emitted.

  • errors: Reverts with InvalidOraclePrice when the oracle price is invalid.

  • reentrancy: No protocol state changes; single external oracle read.

  • access: Public - anyone can check live liquidation status.

  • oracle: Requires a fresh, valid live EUR/USD oracle price.

function shouldTriggerLiquidationLive() external returns (bool shouldLiquidate, uint256 collateralizationRatio);

Returns

NameTypeDescription
shouldLiquidateboolTrue if the protocol is at/below the critical ratio at the live price.
collateralizationRatiouint256Current collateralization ratio in 18-decimal percentage format (1e20 = 100%).

pause

Pauses all vault operations

When paused:

  • No mint/redeem possible
  • Read functions still active

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpauses and resumes operations

Resumes all vault operations after emergency pause

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external onlyRole(EMERGENCY_ROLE);

recoverToken

Recovers tokens accidentally sent to the vault to treasury only

Protections:

  • Cannot recover own vault tokens
  • Tokens are sent to treasury address only
  • Only third-party tokens can be recovered

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken contract address
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Security considerations:

  • Only DEFAULT_ADMIN_ROLE can recover
  • Prevents sending to zero address
  • Validates balance before attempting transfer
  • Uses call() for reliable ETH transfers to any contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

_syncMintWithHedgersOrRevert

Internal helper to notify HedgerPool about user mints.

Mint path must fail if hedger synchronization fails.

Notes:

  • security: Internal hard-fail synchronization helper.

  • validation: No-op on zero amount; otherwise requires downstream HedgerPool success.

  • state-changes: No direct state changes in vault; delegates accounting updates to HedgerPool.

  • events: None in vault.

  • errors: Propagates HedgerPool reverts to preserve atomicity.

  • reentrancy: Not applicable - internal helper.

  • access: Internal helper.

  • oracle: Uses provided cached/fetched fill price from caller context.

function _syncMintWithHedgersOrRevert(uint256 amount, uint256 fillPrice, uint256 qeuroAmount) internal;

Parameters

NameTypeDescription
amountuint256Gross USDC amount allocated to hedger fills (6 decimals).
fillPriceuint256EUR/USD price used for fill accounting (18 decimals).
qeuroAmountuint256QEURO minted amount to track against hedger exposure (18 decimals).

_syncRedeemWithHedgers

Internal helper to notify HedgerPool about user redeems

Releases hedger fills atomically. Reverts propagate, so a paused or otherwise unavailable HedgerPool blocks the redeem instead of desyncing exposure.

Notes:

  • security: Internal helper; relies on HedgerPool access control

  • validation: No additional validation beyond non-zero guard

  • state-changes: None inside the vault; delegates to HedgerPool

  • events: None

  • errors: Propagates HedgerPool reverts to preserve redeem/hedger atomicity

  • reentrancy: Not applicable

  • access: Internal helper

  • oracle: Not applicable

function _syncRedeemWithHedgers(uint256 amount, uint256 redeemPrice, uint256 qeuroAmount) internal;

Parameters

NameTypeDescription
amountuint256Gross USDC returned to the user (6 decimals)
redeemPriceuint256EUR/USD oracle price used for the redeem (18 decimals)
qeuroAmountuint256QEURO amount that was redeemed (18 decimals)

executeWithQuote

Dispatch one signed operation with the original caller and existing accounting.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function executeWithQuote(bytes calldata callData, bytes calldata authorization)
    external
    whenNotPaused
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

preparePoolQuote

Begin an atomic pool route bound to its original user and complete calldata.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function preparePoolQuote(address user, bytes calldata callData, bytes calldata authorization)
    external
    whenNotPaused;

Parameters

NameTypeDescription
useraddressOriginal payer whose nonce and settlement are bound.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

finishPoolQuote

Finish the atomic pool route after its conversion has been consumed.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function finishPoolQuote() external;

emergencyRedeemQEURO

Run the governed budgeted emergency redemption path.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function emergencyRedeemQEURO(uint256 amount, uint256 minimum) external whenNotPaused;

Parameters

NameTypeDescription
amountuint256Amount in the token units of the selected operation.
minimumuint256Minimum acceptable output in the output token's raw units.

_executeSignedExtension

Forward only explicitly declared quote entrypoints to the statically linked extension.

The extension preserves msg.sender, validates mode/access, and delegates only signed selectors.

function _executeSignedExtension() private;

configureExecutionPricing

Configure the execution pricing module while settlement is paused.

Existing admission must be fully acknowledged before changing modules.

Notes:

  • security: Governance only; cannot discard outstanding admission.

  • validation: Requires paused vault, correct module binding and zero pending exposure.

  • state-changes: Updates executionPricing.

  • events: ExecutionPricingConfigured.

  • errors: Propagates access, pause, binding or pending-exposure errors.

  • reentrancy: Calls trusted read-only module checks.

  • access: GOVERNANCE_ROLE while paused.

  • oracle: No price read.

function configureExecutionPricing(address module) external onlyRole(GOVERNANCE_ROLE) whenPaused;

Parameters

NameTypeDescription
moduleaddressVault-bound module, or zero to deactivate after reconciliation.

proposeDevMode

Toggles dev mode to disable price caching requirements

Propose a dev-mode change; enforces a 48-hour timelock before it can be applied

DEV ONLY: When enabled, price deviation checks are skipped for testing

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE

  • validation: No input validation required

  • state-changes: Updates devModeEnabled flag

  • events: Emits DevModeToggled event

  • errors: No errors thrown

  • reentrancy: Not protected - simple state change

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function proposeDevMode(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable dev mode, false to disable

applyDevMode

Apply a previously proposed dev-mode change after the timelock has elapsed.

Finalizes the pending proposal created by proposeDevMode.

Notes:

  • security: Restricted to default admin and time-locked via DEV_MODE_DELAY.

  • validation: Requires active pending proposal and elapsed delay.

  • state-changes: Updates devModeEnabled and clears devModePendingAt.

  • events: Emits DevModeToggled.

  • errors: Reverts when no proposal is pending or delay is not satisfied.

  • reentrancy: Not applicable - simple state transition.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No oracle interaction.

function applyDevMode() external onlyRole(DEFAULT_ADMIN_ROLE);

Events

QEUROminted

Emitted when QEURO is minted

event QEUROminted(address indexed user, uint256 usdcAmount, uint256 qeuroAmount);

QEURORedeemed

Emitted when QEURO is redeemed

event QEURORedeemed(address indexed user, uint256 qeuroAmount, uint256 usdcAmount);

LiquidationRedeemed

Emitted when QEURO is redeemed in liquidation mode (pro-rata)

event LiquidationRedeemed(
    address indexed user, uint256 qeuroAmount, uint256 usdcPayout, uint256 collateralizationRatioBps, bool isPremium
);

Parameters

NameTypeDescription
useraddressAddress of the user redeeming QEURO
qeuroAmountuint256Amount of QEURO redeemed (18 decimals)
usdcPayoutuint256Amount of USDC received (6 decimals)
collateralizationRatioBpsuint256Protocol CR at redemption time (basis points)
isPremiumboolTrue if user received more than fair value (CR > 100%)

HedgerDepositAdded

Emitted when hedger deposits USDC to vault for unified liquidity

event HedgerDepositAdded(address indexed hedgerPool, uint256 usdcAmount, uint256 totalUsdcHeld);

Parameters

NameTypeDescription
hedgerPooladdressAddress of the HedgerPool contract that made the deposit
usdcAmountuint256Amount of USDC deposited (6 decimals)
totalUsdcHelduint256New total USDC held in vault after deposit (6 decimals)

HedgerDepositWithdrawn

Emitted when hedger withdraws USDC from vault

event HedgerDepositWithdrawn(address indexed hedger, uint256 usdcAmount, uint256 totalUsdcHeld);

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger receiving the USDC
usdcAmountuint256Amount of USDC withdrawn (6 decimals)
totalUsdcHelduint256New total USDC held in vault after withdrawal (6 decimals)

ParametersUpdated

Emitted when parameters are changed

OPTIMIZED: Indexed parameter type for efficient filtering

event ParametersUpdated(string indexed parameterType, uint256 mintFee, uint256 redemptionFee);

CollateralizationThresholdsUpdated

Emitted when price deviation protection is triggered

Emitted when collateralization thresholds are updated by governance

Helps monitor potential flash loan attacks

event CollateralizationThresholdsUpdated(
    uint256 indexed minCollateralizationRatioForMinting,
    uint256 indexed criticalCollateralizationRatio,
    address indexed caller
);

Parameters

NameTypeDescription
minCollateralizationRatioForMintinguint256New minimum collateralization ratio for minting (in 18 decimals)
criticalCollateralizationRatiouint256New critical collateralization ratio for liquidation (in 18 decimals)
calleraddressAddress of the governance role holder who updated the thresholds

PriceDeviationDetected

event PriceDeviationDetected(
    uint256 currentPrice, uint256 lastValidPrice, uint256 deviationBps, uint256 blockNumber
);

PriceCacheUpdated

Emitted when price cache is manually updated by governance

event PriceCacheUpdated(uint256 oldPrice, uint256 newPrice, uint256 blockNumber);

Parameters

NameTypeDescription
oldPriceuint256Previous cached price
newPriceuint256New cached price
blockNumberuint256Block number when cache was updated

DevModeToggled

Emitted when dev mode is toggled

event DevModeToggled(bool enabled, address indexed caller);

Parameters

NameTypeDescription
enabledboolWhether dev mode is enabled or disabled
calleraddressAddress that triggered the toggle

DevModeProposed

Emitted when a dev-mode change is proposed

event DevModeProposed(bool pending, uint256 activatesAt);

Parameters

NameTypeDescription
pendingboolThe proposed dev-mode value
activatesAtuint256Timestamp at which the change can be applied

StakingVaultConfigured

Emitted when an external staking vault adapter is configured.

event StakingVaultConfigured(uint256 indexed vaultId, address indexed adapter, bool active);

ExternalVaultLossRealized

event ExternalVaultLossRealized(uint256 indexed vaultId, uint256 previousPrincipal, uint256 currentUnderlying);

DefaultStakingVaultUpdated

event DefaultStakingVaultUpdated(uint256 indexed previousVaultId, uint256 indexed newVaultId);

RedemptionPriorityUpdated

event RedemptionPriorityUpdated(uint256[] vaultIds);

StQEURORegistered

event StQEURORegistered(
    address indexed factory, uint256 indexed vaultId, address indexed stQEUROToken, string vaultName
);

UsdcDeployedToExternalVault

event UsdcDeployedToExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalInVault);

VaultYieldDistributed

Emitted when harvested external-vault yield is distributed across hedger/user/treasury.

event VaultYieldDistributed(
    uint256 indexed vaultId, uint256 realizedYield, uint256 hedgerShare, uint256 userShare, uint256 treasuryShare
);

Parameters

NameTypeDescription
vaultIduint256Vault id whose yield was distributed
realizedYielduint256Total USDC yield realized from the adapter (6 decimals)
hedgerShareuint256USDC routed to the hedger funding recipient (6 decimals)
userShareuint256USDC credited into the stQEURO vault as QEURO backing (6 decimals)
treasuryShareuint256USDC routed to the treasury (6 decimals)

FundingRateUpdated

Emitted when governance updates the annualized hedger funding rate.

event FundingRateUpdated(uint256 oldRateBps, uint256 newRateBps);

Parameters

NameTypeDescription
oldRateBpsuint256Previous funding rate (basis points)
newRateBpsuint256New funding rate (basis points)

HedgerYieldRecipientUpdated

Emitted when the hedger yield recipient is updated by governance.

event HedgerYieldRecipientUpdated(address indexed oldRecipient, address indexed newRecipient);

Parameters

NameTypeDescription
oldRecipientaddressPrevious recipient address
newRecipientaddressNew recipient address

UsdcWithdrawnFromExternalVault

event UsdcWithdrawnFromExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalInVault);

HedgerRewardFeeSplitUpdated

event HedgerRewardFeeSplitUpdated(uint256 previousSplit, uint256 newSplit);

OracleUpdated

Emitted when the oracle address is changed via updateOracle

event OracleUpdated(address indexed oldOracle, address indexed newOracle);

ProtocolFeeRouted

event ProtocolFeeRouted(string sourceType, uint256 totalFee, uint256 hedgerReserveShare, uint256 collectorShare);

VaultYieldBreakdown

Retired hedger base (always zero) and staking haircut, in USDC (6 decimals).

event VaultYieldBreakdown(uint256 indexed vaultId, uint256 hedgerBase, uint256 stakingYieldHaircut);

HedgerStakingYieldHaircutUpdated

Governance changed the percentage of gross staking yield paid to the hedger.

event HedgerStakingYieldHaircutUpdated(uint256 oldBps, uint256 newBps);

ExecutionPricingConfigured

Emitted when governance configures the execution pricing module.

event ExecutionPricingConfigured(address indexed module);

Errors

InsufficientCollateralization

Collateralization is below the minimum required to mint.

Included in the vault ABI for errors propagated by its linked pricing library.

error InsufficientCollateralization();

NoActiveHedgerLiquidity

Minting requires available liquidity from an active hedger.

Included in the vault ABI for errors propagated by its linked pricing library.

error NoActiveHedgerLiquidity();

PercentageTooHigh

Retired yield-fee validation error retained for ABI compatibility.

error PercentageTooHigh();

NotInitialized

Retained ABI error for staking recipients that have not initialized their share supply.

Emitted by the linked yield settlement library.

error NotInitialized();

Structs

LiquidationCommitParams

struct LiquidationCommitParams {
    address redeemer;
    uint256 qeuroAmount;
    uint256 totalSupply;
    uint256 usdcPayout;
    uint256 netUsdcPayout;
    uint256 fee;
    uint256 collateralizationRatioBps;
    uint256 eurUsdPrice;
    bool isValidPrice;
    bool isPremium;
    uint256 externalWithdrawalAmount;
}

MintCommitPayload

struct MintCommitPayload {
    address payer;
    address qeuroRecipient;
    uint256 usdcAmount;
    uint256 fee;
    uint256 netAmount;
    uint256 qeuroToMint;
    uint256 eurUsdPrice;
    bool isValidPrice;
    uint256 targetVaultId;
}

RedeemCommitPayload

struct RedeemCommitPayload {
    address redeemer;
    uint256 qeuroAmount;
    uint256 usdcToReturn;
    uint256 netUsdcToReturn;
    uint256 fee;
    uint256 eurUsdPrice;
    bool isValidPrice;
    uint256 externalWithdrawalAmount;
}

SecureUpgradeable

Git Source

Inherits: UUPSUpgradeable, AccessControlUpgradeable

Title: SecureUpgradeable

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Secure base contract for upgradeable contracts with timelock protection

Replaces UUPSUpgradeable with timelock and multi-sig requirements

Note: security-contact: team@quantillon.money

Constants

UPGRADER_ROLE

Role for upgrade operations

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

EMERGENCY_DISABLE_DELAY

Minimum delay before a proposed emergency-disable takes effect (24h)

uint256 public constant EMERGENCY_DISABLE_DELAY = 24 hours

EMERGENCY_DISABLE_QUORUM

Emergency-disable approvals required before apply can succeed

uint256 public constant EMERGENCY_DISABLE_QUORUM = 2

EMERGENCY_DISABLE_STORAGE_SLOT

Unstructured storage slot to avoid shifting child storage layouts.

bytes32 private constant EMERGENCY_DISABLE_STORAGE_SLOT =
    keccak256("quantillon.secure-upgradeable.emergency-disable.storage.v1")

State Variables

timelock

Timelock contract for secure upgrades

ITimelockUpgradeable public timelock

secureUpgradesEnabled

Whether the contract is using secure upgrades

bool public secureUpgradesEnabled

emergencyDisablePendingAt

Timestamp at which emergencyDisable can be applied (0 = no pending proposal)

Deadline in seconds, compared against block.timestamp.

uint256 public emergencyDisablePendingAt

Functions

_emergencyDisableStorage

function _emergencyDisableStorage() private pure returns (EmergencyDisableStorage storage ds);

onlyTimelock

modifier onlyTimelock() ;

_onlyTimelock

Reverts if caller is not the timelock contract

Used by onlyTimelock modifier; ensures upgrade execution comes from timelock only

Notes:

  • security: Access control for upgrade execution

  • validation: Timelock must be set and msg.sender must equal timelock

  • state-changes: None

  • events: None

  • errors: NotAuthorized if timelock zero or caller not timelock

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _onlyTimelock() internal view;

_protocolTime

Returns canonical protocol time

Base implementation returns block.timestamp. Contracts that hold their own TIME_PROVIDER override this and read it directly. Deliberately makes no external call: the timelock is an upgrade authority, not a time source, and it is not guaranteed to expose currentTime() (a stock OpenZeppelin TimelockController does not).

Notes:

  • security: No external call; cannot revert or be griefed by the timelock

  • validation: None required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view virtual returns (uint256);

Returns

NameTypeDescription
<none>uint256Canonical protocol time in seconds

__SecureUpgradeable_init

Initializes the SecureUpgradeable contract

Sets up the secure upgrade system with timelock protection

Notes:

  • security: Validates timelock address and initializes secure upgrade system

  • validation: Validates _timelock is not address(0)

  • state-changes: Initializes timelock, enables secure upgrades, sets up access control

  • events: Emits TimelockSet and SecureUpgradesToggled events

  • errors: Throws "SecureUpgradeable: Invalid timelock" if _timelock is address(0)

  • reentrancy: Protected by onlyInitializing modifier

  • access: Internal function - only callable during initialization

  • oracle: No oracle dependencies

function __SecureUpgradeable_init(address _timelock) internal onlyInitializing;

Parameters

NameTypeDescription
_timelockaddressAddress of the timelock contract

setTimelock

Set the timelock contract

Configures the timelock contract for secure upgrade management

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function setTimelock(address _timelock) external;

Parameters

NameTypeDescription
_timelockaddressAddress of the timelock contract

toggleSecureUpgrades

(Re-)enable secure upgrades

Enables secure upgrades. Disabling is intentionally NOT possible through this function: it must go through the quorum-gated, timelocked emergency-disable flow (proposeEmergencyDisableSecureUpgrades → approveEmergencyDisableSecureUpgrades → applyEmergencyDisableSecureUpgrades). Passing enabled=false reverts (an instant disable here would let a single admin bypass the emergency flow and then call emergencyUpgrade with no timelock).

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function toggleSecureUpgrades(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolMust be true; false reverts (use the emergency-disable flow)

proposeUpgrade

Propose an upgrade through the timelock

Initiates a secure upgrade proposal with timelock delay and multi-sig requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function proposeUpgrade(address newImplementation, string calldata description, uint256 customDelay)
    external
    onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the upgrade
customDelayuint256Optional custom delay

executeUpgrade

Execute an upgrade through the timelock

Executes a previously proposed upgrade after timelock delay

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function executeUpgrade(address newImplementation) external onlyTimelock;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

emergencyUpgrade

Emergency upgrade (bypasses timelock, requires emergency mode)

Allows emergency upgrades when secure upgrades are disabled or timelock is unavailable

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyUpgrade(address newImplementation, string calldata description) external onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the emergency upgrade

_authorizeUpgrade

Authorize upgrade (overrides UUPSUpgradeable)

Internal function that determines upgrade authorization based on secure upgrade settings

function _authorizeUpgrade(address newImplementation) internal view override;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

isUpgradePending

Check if an upgrade is pending

Checks if there is a pending upgrade for the specified implementation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isUpgradePending(address implementation) external view returns (bool isPending);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
isPendingboolWhether the upgrade is pending

getPendingUpgrade

Get pending upgrade details

Returns detailed information about a pending upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPendingUpgrade(address implementation)
    external
    view
    returns (ITimelockUpgradeable.PendingUpgrade memory upgrade);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
upgradeITimelockUpgradeable.PendingUpgradePending upgrade details

canExecuteUpgrade

Check if an upgrade can be executed

Checks if a pending upgrade has passed the timelock delay and can be executed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function canExecuteUpgrade(address implementation) external view returns (bool canExecute);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
canExecuteboolWhether the upgrade can be executed

getUpgradeSecurityStatus

Get upgrade security status

Returns the current security configuration for upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getUpgradeSecurityStatus()
    external
    view
    returns (address timelockAddress, bool secureUpgradesEnabled_, bool hasTimelock);

Returns

NameTypeDescription
timelockAddressaddressAddress of the timelock contract
secureUpgradesEnabled_boolWhether secure upgrades are enabled
hasTimelockboolWhether timelock is set

proposeEmergencyDisableSecureUpgrades

Disable secure upgrades in emergency

Propose disabling secure upgrades; enforces a 24-hour timelock

Disables secure upgrades for emergency situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function proposeEmergencyDisableSecureUpgrades() external onlyRole(DEFAULT_ADMIN_ROLE);

approveEmergencyDisableSecureUpgrades

Register an admin approval for the active emergency-disable proposal.

Records an approval from a DEFAULT_ADMIN_ROLE address for the current proposal. Uses per-proposal bitmap to prevent duplicate approvals from the same address.

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE; prevents double-approval per admin.

  • validation: Reverts if no active proposal or caller already approved.

  • state-changes: Marks caller as approved and increments approvalCount in storage.

  • events: Emits EmergencyDisableApproved with updated approval count.

  • errors: NotActive if no pending proposal; NoChangeDetected if already approved.

  • reentrancy: Not applicable – function is external but has no external calls after state changes.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No oracle dependencies.

function approveEmergencyDisableSecureUpgrades() external onlyRole(DEFAULT_ADMIN_ROLE);

applyEmergencyDisableSecureUpgrades

Apply a previously proposed emergency-disable after the timelock has elapsed.

Disables secure upgrades permanently for this deployment once quorum and delay are satisfied. Resets pending state so a fresh proposal is required for any future changes.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE, quorum approvals and elapsed delay.

  • validation: Reverts on mismatched proposal id, missing quorum or no pending proposal.

  • state-changes: Clears emergencyDisablePendingAt and approvalCount, sets secureUpgradesEnabled=false.

  • events: Emits SecureUpgradesToggled(false) on successful application.

  • errors: NotActive if no pending or delay not elapsed; NotAuthorized on id mismatch or quorum not met.

  • reentrancy: Not applicable – no external calls after critical state changes.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No oracle dependencies.

function applyEmergencyDisableSecureUpgrades(uint256 expectedProposalId) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
expectedProposalIduint256Proposal id the caller expects to apply (replay/mismatch protection).

emergencyDisableProposalId

Returns the current emergency-disable proposal id.

Value is 0 when no proposal has ever been created.

Notes:

  • security: View-only helper; no access restriction.

  • validation: No input validation required.

  • state-changes: None – pure read from dedicated emergency-disable storage.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public – any caller may inspect current proposal id.

  • oracle: No oracle dependencies.

function emergencyDisableProposalId() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256proposalId The active or last-used emergency-disable proposal id.

emergencyDisableApprovalCount

Returns the current approval count for the active emergency-disable proposal.

Reads the aggregate number of admin approvals recorded for the latest proposal.

Notes:

  • security: View-only helper; no access restriction.

  • validation: No input validation required.

  • state-changes: None – pure read from dedicated emergency-disable storage.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public – any caller may inspect approval count.

  • oracle: No oracle dependencies.

function emergencyDisableApprovalCount() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256approvalCount Number of approvals for the current proposal.

emergencyDisableQuorum

Returns the quorum required to apply the emergency disable.

Exposes the EMERGENCY_DISABLE_QUORUM compile-time constant.

Notes:

  • security: View-only helper; no access restriction.

  • validation: No input validation required.

  • state-changes: None – pure return of constant.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – pure function.

  • access: Public – any caller may inspect required quorum.

  • oracle: No oracle dependencies.

function emergencyDisableQuorum() public pure returns (uint256);

Returns

NameTypeDescription
<none>uint256quorum Number of approvals required to apply emergency-disable.

hasEmergencyDisableApproval

Returns whether a given approver address approved a specific emergency-disable proposal.

Returns false when approver is zero or proposalId is zero for safety.

Notes:

  • security: View-only helper; no access restriction.

  • validation: Treats zero proposalId or zero approver as “not approved”.

  • state-changes: None – pure read from dedicated emergency-disable storage.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public – any caller may inspect approval status.

  • oracle: No oracle dependencies.

function hasEmergencyDisableApproval(uint256 proposalId, address approver) public view returns (bool hasApproved_);

Parameters

NameTypeDescription
proposalIduint256The proposal identifier to inspect.
approveraddressThe admin address whose approval status is queried.

Returns

NameTypeDescription
hasApproved_boolTrue if the approver has recorded an approval for proposalId.

enableSecureUpgrades

Enable secure upgrades after emergency

Re-enables secure upgrades after emergency situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function enableSecureUpgrades() external onlyRole(DEFAULT_ADMIN_ROLE);

Events

TimelockSet

event TimelockSet(address indexed timelock);

SecureUpgradesToggled

event SecureUpgradesToggled(bool enabled);

SecureUpgradeAuthorized

event SecureUpgradeAuthorized(address indexed newImplementation, address indexed authorizedBy, string description);

EmergencyDisableProposed

Emitted when an emergency-disable proposal is created

event EmergencyDisableProposed(uint256 indexed proposalId, uint256 activatesAt);

EmergencyDisableApproved

event EmergencyDisableApproved(uint256 indexed proposalId, address indexed approver, uint256 approvalCount);

Structs

EmergencyDisableStorage

struct EmergencyDisableStorage {
    uint256 proposalId;
    uint256 approvalCount;
    mapping(uint256 => mapping(address => bool)) hasApproved;
}

TimelockUpgradeable

Git Source

Inherits: Initializable, AccessControlUpgradeable, PausableUpgradeable, IVersioned

Title: TimelockUpgradeable

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Secure upgrade mechanism with timelock and multi-sig requirements

Replaces unrestricted upgrade capability with governance-controlled upgrades

Note: security-contact: team@quantillon.money

Constants

UPGRADE_DELAY

Minimum delay for upgrades (48 hours)

uint256 public constant UPGRADE_DELAY = 48 hours

MAX_UPGRADE_DELAY

Maximum delay for upgrades (7 days)

uint256 public constant MAX_UPGRADE_DELAY = 7 days

MIN_MULTISIG_APPROVALS

Minimum number of multi-sig approvals required

uint256 public constant MIN_MULTISIG_APPROVALS = 2

MAX_MULTISIG_SIGNERS

Maximum number of multi-sig signers

uint256 public constant MAX_MULTISIG_SIGNERS = 5

MAX_PROPOSAL_AGE

Maximum age of a pending upgrade proposal (prevents stale proposal execution)

uint256 public constant MAX_PROPOSAL_AGE = 30 days

UPGRADE_PROPOSER_ROLE

Role for proposing upgrades

bytes32 public constant UPGRADE_PROPOSER_ROLE = keccak256("UPGRADE_PROPOSER_ROLE")

UPGRADE_EXECUTOR_ROLE

Role for executing upgrades after timelock

bytes32 public constant UPGRADE_EXECUTOR_ROLE = keccak256("UPGRADE_EXECUTOR_ROLE")

EMERGENCY_UPGRADER_ROLE

Role for emergency upgrades (bypasses timelock)

bytes32 public constant EMERGENCY_UPGRADER_ROLE = keccak256("EMERGENCY_UPGRADER_ROLE")

MULTISIG_MANAGER_ROLE

Role for managing multi-sig signers

bytes32 public constant MULTISIG_MANAGER_ROLE = keccak256("MULTISIG_MANAGER_ROLE")

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

State Variables

pendingUpgrades

Pending upgrades by implementation address

mapping(address => PendingUpgrade) public pendingUpgrades

multisigSigners

Multi-sig signers

mapping(address => bool) public multisigSigners

multisigSignerCount

Number of active multi-sig signers

uint256 public multisigSignerCount

upgradeApprovals

Upgrade approvals by signer

mapping(address => mapping(address => bool)) public upgradeApprovals

upgradeApprovalCount

Number of approvals for each pending upgrade

mapping(address => uint256) public upgradeApprovalCount

emergencyMode

Whether emergency mode is active

bool public emergencyMode

_multisigSignersList

Ordered list of multisig signers for approval clearing

address[] internal _multisigSignersList

_multisigSignerIndexPlusOne

1-based index mapping for O(1) signer removal from _multisigSignersList

mapping(address => uint256) internal _multisigSignerIndexPlusOne

_pendingUpgradesList

Ordered list of pending upgrade addresses for signer clearing

address[] internal _pendingUpgradesList

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

onlyMultisigSigner

modifier onlyMultisigSigner() ;

onlyEmergencyUpgrader

modifier onlyEmergencyUpgrader() ;

_onlyEmergencyUpgrader

Reverts if caller is not emergency upgrader or emergency mode is not active

Used by onlyEmergencyUpgrader modifier; allows emergency upgrades only when enabled

Notes:

  • security: Restricts emergency upgrade path to EMERGENCY_UPGRADER_ROLE when emergencyMode

  • validation: Caller must have role and emergencyMode must be true

  • state-changes: None

  • events: None

  • errors: NotEmergencyRole if not authorized or not emergency mode

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _onlyEmergencyUpgrader() internal view;

initialize

Initializes the timelock contract with admin privileges

Sets up access control roles and pausability. Can only be called once.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin) public initializer;

Parameters

NameTypeDescription
adminaddressThe address that will receive admin and upgrade proposer roles

proposeUpgrade

Propose an upgrade with timelock

Proposes an upgrade with timelock delay and multi-sig approval requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to UPGRADE_PROPOSER_ROLE

  • oracle: No oracle dependencies

function proposeUpgrade(address newImplementation, string calldata description, uint256 customDelay)
    external
    onlyRole(UPGRADE_PROPOSER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the upgrade
customDelayuint256Optional custom delay (must be >= UPGRADE_DELAY)

approveUpgrade

Approve a pending upgrade (multi-sig signer only)

Allows multi-sig signers to approve pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to multi-sig signers

  • oracle: No oracle dependencies

function approveUpgrade(address implementation) external onlyMultisigSigner;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to approve

revokeUpgradeApproval

Revoke approval for a pending upgrade

Allows multi-sig signers to revoke their approval for pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to multi-sig signers

  • oracle: No oracle dependencies

function revokeUpgradeApproval(address implementation) external onlyMultisigSigner;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to revoke approval for

executeUpgrade

Execute an upgrade after timelock and multi-sig approval

Executes an upgrade after timelock delay and sufficient multi-sig approvals

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to UPGRADE_EXECUTOR_ROLE

  • oracle: No oracle dependencies

function executeUpgrade(address implementation) external onlyRole(UPGRADE_EXECUTOR_ROLE);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to execute

cancelUpgrade

Cancel a pending upgrade (only proposer or admin)

Allows proposer or admin to cancel pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to proposer or admin

  • oracle: No oracle dependencies

function cancelUpgrade(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to cancel

emergencyUpgrade

Emergency upgrade (bypasses timelock, requires emergency mode)

Performs emergency upgrade bypassing timelock and multi-sig requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to emergency upgrader role

  • oracle: No oracle dependencies

function emergencyUpgrade(address newImplementation, string calldata description) external onlyEmergencyUpgrader;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the emergency upgrade

addMultisigSigner

Add a multi-sig signer

Adds a new multi-sig signer to the timelock system

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to MULTISIG_MANAGER_ROLE

  • oracle: No oracle dependencies

function addMultisigSigner(address signer) external onlyRole(MULTISIG_MANAGER_ROLE);

Parameters

NameTypeDescription
signeraddressAddress of the signer to add

removeMultisigSigner

Remove a multi-sig signer

Removes a multi-sig signer from the timelock system

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to MULTISIG_MANAGER_ROLE

  • oracle: No oracle dependencies

function removeMultisigSigner(address signer) external onlyRole(MULTISIG_MANAGER_ROLE);

Parameters

NameTypeDescription
signeraddressAddress of the signer to remove

toggleEmergencyMode

Toggle emergency mode

Toggles emergency mode for emergency upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to EMERGENCY_UPGRADER_ROLE

  • oracle: No oracle dependencies

function toggleEmergencyMode(bool enabled, string calldata reason) external onlyRole(EMERGENCY_UPGRADER_ROLE);

Parameters

NameTypeDescription
enabledboolWhether to enable emergency mode
reasonstringReason for the emergency mode change

getPendingUpgrade

Get pending upgrade details

Returns pending upgrade details for a given implementation

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getPendingUpgrade(address implementation) external view returns (PendingUpgrade memory upgrade);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
upgradePendingUpgradePending upgrade details

canExecuteUpgrade

Check if an upgrade can be executed

Checks if an upgrade can be executed based on timelock and approval requirements

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function canExecuteUpgrade(address implementation) external view returns (bool canExecute);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
canExecuteboolWhether the upgrade can be executed

hasUpgradeApproval

Get upgrade approval status for a signer

Returns whether a signer has approved a specific upgrade

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function hasUpgradeApproval(address signer, address implementation) external view returns (bool approved);

Parameters

NameTypeDescription
signeraddressAddress of the signer
implementationaddressAddress of the implementation

Returns

NameTypeDescription
approvedboolWhether the signer has approved the upgrade

getMultisigSigners

Get all multi-sig signers

Returns array of all multi-sig signer addresses

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getMultisigSigners() external view returns (address[] memory signers);

Returns

NameTypeDescription
signersaddress[]Array of signer addresses

currentTime

Returns protocol time from the shared TimeProvider

Exposes the canonical time source to dependent contracts (e.g. SecureUpgradeable)

Notes:

  • security: Returns canonical protocol time managed by immutable shared provider

  • validation: No input validation required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external state mutation

  • access: Public view utility

  • oracle: No oracle dependencies

function currentTime() external view returns (uint256);

_clearUpgradeApprovals

Clear all approvals for an implementation

Clear all approvals for a specific implementation

Clears all approvals for a specific implementation

Resets approval counts for a pending upgrade and removes it from the ordered pending list

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

  • security: Internal helper used after execute/cancel paths; assumes caller already validated upgrade existence

  • validation: Assumes implementation is currently tracked in _pendingUpgradesList

  • state-changes: Sets upgradeApprovalCount[implementation] to zero and clears all signer approvals

  • events: No events emitted directly; caller is responsible for emitting high-level events

  • errors: None - function is best-effort cleanup

  • reentrancy: Not applicable - internal function with no external calls

  • access: Internal function only

  • oracle: No oracle dependencies

function _clearUpgradeApprovals(address implementation) internal;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

_removePendingUpgrade

Remove an implementation from the ordered list of pending upgrades

Uses swap-and-pop to maintain a compact array of pending upgrades for efficient iteration

Notes:

  • security: Internal helper; assumes caller has already validated that the upgrade is pending

  • validation: Performs a linear scan over _pendingUpgradesList and stops at first match

  • state-changes: Updates _pendingUpgradesList by replacing the removed element with the last one and shrinking the array

  • events: No events emitted directly; high-level events are emitted by caller functions

  • errors: None - function silently returns if no match is found

  • reentrancy: Not applicable - internal function with no external calls

  • access: Internal function only

  • oracle: No oracle dependencies

function _removePendingUpgrade(address implementation) internal;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to remove from _pendingUpgradesList

_clearSignerApprovals

Clear all approvals from a specific signer

Clears all approvals from a specific signer

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _clearSignerApprovals(address signer) internal;

Parameters

NameTypeDescription
signeraddressAddress of the signer

_addMultisigSigner

Add a multisig signer (internal)

Adds a multisig signer internally

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _addMultisigSigner(address signer) internal;

Parameters

NameTypeDescription
signeraddressAddress of the signer

pause

Pause the timelock contract

Pauses the timelock contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function pause() external onlyRole(DEFAULT_ADMIN_ROLE);

unpause

Unpause the timelock contract

Unpauses the timelock contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);

constructor

Constructor for TimelockUpgradeable contract

Sets up the time provider and disables initializers for security

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderTimeProvider contract for centralized time management

Events

UpgradeProposed

event UpgradeProposed(
    address indexed implementation,
    uint256 proposedAt,
    uint256 executableAt,
    string description,
    address indexed proposer
);

UpgradeApproved

event UpgradeApproved(address indexed implementation, address indexed signer, uint256 approvalCount);

UpgradeExecuted

event UpgradeExecuted(address indexed implementation, address indexed executor, uint256 executedAt);

UpgradeCancelled

event UpgradeCancelled(address indexed implementation, address indexed canceller);

MultisigSignerAdded

event MultisigSignerAdded(address indexed signer);

MultisigSignerRemoved

event MultisigSignerRemoved(address indexed signer);

EmergencyModeToggled

event EmergencyModeToggled(bool enabled, string reason);

Structs

PendingUpgrade

struct PendingUpgrade {
    address implementation;
    address proposingProxy; // proxy contract that initiated this upgrade proposal
    uint256 proposedAt;
    uint256 executableAt;
    uint256 expiryAt; // proposal expires after MAX_PROPOSAL_AGE to prevent stale execution
    string description;
    bool isEmergency;
    address proposer;
}

UserPool

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IVersioned

Title: UserPool

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Manages QEURO user deposits, staking, and yield distribution

Main characteristics:

  • User deposit and withdrawal management
  • QEURO staking mechanism with rewards
  • Yield distribution system
  • Fee structure for protocol sustainability
  • Emergency pause mechanism for crisis situations
  • Upgradeable via UUPS pattern

Deposit mechanics:

  • Users deposit USDC to receive QEURO
  • QEURO is minted based on current EUR/USD exchange rate
  • Deposit fees charged for protocol revenue
  • Deposits are tracked per user for analytics

Staking mechanics:

  • Users can stake their QEURO for additional rewards
  • Staking APY provides yield on staked QEURO
  • Unstaking has a cooldown period to prevent abuse
  • Rewards are distributed based on staking duration and amount

Withdrawal mechanics:

  • Users can withdraw their QEURO back to USDC
  • Withdrawal fees charged for protocol revenue
  • Withdrawals are processed based on current EUR/USD rate
  • Staked QEURO must be unstaked before withdrawal

Yield distribution:

  • Yield is distributed to stakers based on their stake amount
  • Performance fees charged on yield distributions
  • Yield sources include protocol fees and yield shift mechanisms
  • Real-time yield tracking and distribution

Fee structure:

  • Deposit fees for creating QEURO from USDC
  • Withdrawal fees for converting QEURO back to USDC
  • Performance fees on yield distributions
  • Dynamic fee adjustment based on market conditions

Security features:

  • Role-based access control for all critical operations
  • Reentrancy protection for all external calls
  • Emergency pause mechanism for crisis situations
  • Upgradeable architecture for future improvements
  • Secure deposit and withdrawal management
  • Staking cooldown mechanisms
  • Batch size limits to prevent DoS attacks
  • Gas optimization through storage read caching

Integration points:

  • QEURO token for minting and burning
  • USDC for deposits and withdrawals
  • QuantillonVault for QEURO minting/burning
  • Yield shift mechanism for yield management
  • Vault math library for calculations

Note: security-contact: team@quantillon.money

Constants

GOVERNANCE_ROLE

Role for governance operations (parameter updates, emergency actions)

keccak256 hash avoids role collisions with other contracts

Should be assigned to governance multisig or DAO

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

Role for emergency operations (pause, emergency withdrawals)

keccak256 hash avoids role collisions with other contracts

Should be assigned to emergency multisig

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

MAX_REWARD_PERIOD

uint256 public constant MAX_REWARD_PERIOD = 365 days

MAX_BATCH_SIZE

Maximum batch size for deposit operations to prevent DoS

Prevents out-of-gas attacks through large arrays

uint256 public constant MAX_BATCH_SIZE = 100

MAX_REWARD_BATCH_SIZE

Maximum batch size for reward claim operations to prevent DoS

Prevents out-of-gas attacks through large user arrays

uint256 public constant MAX_REWARD_BATCH_SIZE = 50

State Variables

qeuro

QEURO token contract for minting and burning

Used for all QEURO minting and burning operations

Should be the official QEURO token contract

IQEUROToken public qeuro

usdc

USDC token contract for deposits and withdrawals

Used for all USDC deposits and withdrawals

Should be the official USDC contract on the target network

IERC20 public usdc

_flashLoanBalanceBefore

USDC balance before flash loan check (used by flashLoanProtection modifier)

uint256 private _flashLoanBalanceBefore

vault

Main Quantillon vault for QEURO operations

Used for QEURO minting and burning operations

Should be the official QuantillonVault contract

IQuantillonVault public vault

oracle

Oracle for EUR/USD price feeds (Chainlink or Stork via router)

Used for converting QEURO supply to USDC equivalent in analytics

IOracle public oracle

yieldShift

Yield shift mechanism for yield management

Handles yield distribution and management

Used for yield calculations and distributions

IYieldShift public yieldShift

treasury

Treasury address for ETH recovery

SECURITY: Only this address can receive ETH from recoverETH function

address public treasury

stakingAPY

Staking APY in basis points

Example: 500 = 5% staking APY

Used for calculating staking rewards

uint256 public stakingAPY

depositAPY

Base deposit APY in basis points

Example: 200 = 2% base deposit APY

Used for calculating deposit rewards

uint256 public depositAPY

minStakeAmount

Minimum amount required for staking (in QEURO)

Example: 100 * 1e18 = 100 QEURO minimum stake

Prevents dust staking and reduces gas costs

uint256 public minStakeAmount

unstakingCooldown

Cooldown period for unstaking (in seconds)

Example: 7 days = 604,800 seconds

Prevents rapid staking/unstaking cycles

uint256 public unstakingCooldown

performanceFee

Fee charged on yield distributions (in basis points)

Example: 1000 = 10% performance fee on staking rewards

Revenue source for the protocol

uint256 public performanceFee

totalStakes

Total QEURO staked across all users

Sum of all staked QEURO amounts

Used for yield distribution calculations

uint256 public totalStakes

totalUsers

Number of unique users who have deposited

Count of unique addresses that have made deposits

Used for protocol analytics and governance

uint256 public totalUsers

userInfo

User information by address

Maps user addresses to their detailed information

Used to track user deposits, stakes, and rewards

mapping(address => UserInfo) public userInfo

hasDeposited

Whether a user has ever deposited

Maps user addresses to their deposit status

Used to track unique users and prevent double counting

mapping(address => bool) public hasDeposited

accumulatedYieldPerShare

Accumulated yield per staked QEURO share

Used for calculating user rewards based on their stake amount

Increases over time as yield is distributed

uint256 public accumulatedYieldPerShare

lastYieldDistribution

Timestamp of last yield distribution

Used to track when yield was last distributed

Used for yield calculation intervals

uint256 public lastYieldDistribution

totalYieldDistributed

Total yield distributed to users

Sum of all yield distributed to users

Used for protocol analytics and governance

uint256 public totalYieldDistributed

totalUserDeposits

Total USDC deposits across all users (in USDC decimals - 6)

Tracks the sum of all USDC deposits made by users

Used for protocol analytics and collateralization calculations

uint256 public totalUserDeposits

totalUserWithdrawals

Total QEURO withdrawals across all users (in QEURO decimals - 18)

Tracks the sum of all QEURO withdrawals made by users

Used for protocol analytics and supply tracking

uint256 public totalUserWithdrawals

userDeposits

User deposit tracking with oracle ratios

Maps user addresses to their deposit history with oracle ratios

Used for detailed analytics and audit trails

mapping(address => UserDepositInfo[]) public userDeposits

userWithdrawals

User withdrawal tracking with oracle ratios

Maps user addresses to their withdrawal history with oracle ratios

Used for detailed analytics and audit trails

mapping(address => UserWithdrawalInfo[]) public userWithdrawals

userLastRewardBlock

mapping(address => uint256) public userLastRewardBlock

pendingUsdcWithdrawals

Pending USDC withdrawals for users whose transfers failed (e.g. USDC blacklist)

mapping(address => uint256) public pendingUsdcWithdrawals

totalPendingUsdcWithdrawals

Aggregate USDC reserved for pending user withdrawals.

uint256 public totalPendingUsdcWithdrawals

pendingUsdcLiabilitiesInitialized

Whether legacy pending-withdrawal liabilities have been included in the aggregate.

bool public pendingUsdcLiabilitiesInitialized

signedRouteActive

Transaction-local guard for the quote wrapper, appended without moving existing storage.

bool private signedRouteActive

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

flashLoanProtection

Modifier to protect against flash loan attacks

Uses the FlashLoanProtectionLibrary to check USDC balance consistency

modifier flashLoanProtection() ;

onlySelf

modifier onlySelf() ;

_onlySelf

Reverts unless caller is this contract.

Internal guard used by onlySelf for commit-phase helpers reached via explicit self-calls.

Notes:

  • security: Prevents direct external invocation of self-call commit paths.

  • validation: Requires msg.sender == address(this).

  • state-changes: None.

  • events: None.

  • errors: Reverts with NotAuthorized when caller is not self.

  • reentrancy: No external calls.

  • access: Internal helper used by modifier.

  • oracle: No oracle dependencies.

function _onlySelf() internal view;

_flashLoanProtectionBefore

function _flashLoanProtectionBefore() private;

_flashLoanProtectionAfter

function _flashLoanProtectionAfter() private view;

constructor

Constructor for UserPool contract

Sets up the time provider and disables initializers for security

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderTimeProvider contract for centralized time management

_protocolTime

Returns canonical protocol time from this contract's TimeProvider

Overrides the SecureUpgradeable base, which returns block.timestamp.

Notes:

  • security: Reads the immutable TimeProvider set at construction

  • validation: None required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Canonical protocol time in seconds

initialize

Initializes the UserPool contract

Initializes the UserPool with all required contracts and default parameters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Initializes all contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: Requires oracle for analytics functions

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _vault,
    address _oracle,
    address _yieldShift,
    address _timelock,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and governance roles
_qeuroaddressAddress of the QEURO token contract
_usdcaddressAddress of the USDC token contract
_vaultaddressAddress of the QuantillonVault contract
_oracleaddressAddress of the Chainlink Oracle contract
_yieldShiftaddressAddress of the YieldShift contract
_timelockaddressAddress of the timelock contract
_treasuryaddressAddress of the treasury contract

initializePendingUsdcLiabilitiesV2

Backfills aggregate pending USDC liabilities after an implementation upgrade.

Runs once through reinitializer(2), reserving the existing USDC balance before recovery is enabled.

Notes:

  • security: Governance-only migration; configured-USDC recovery stays disabled until completion.

  • validation: Conservatively reserves the full pre-migration USDC balance.

  • state-changes: Initializes totalPendingUsdcWithdrawals and marks the aggregate ready.

  • events: Emits initializer framework events where applicable.

  • errors: Reverts when already initialized.

  • reentrancy: Performs only a balance read on the configured USDC token.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function initializePendingUsdcLiabilitiesV2() external onlyRole(GOVERNANCE_ROLE) reinitializer(2);

_setUserPoolContractReferences

Sets core contract references after initialization to reduce stack depth

Called from initialize to avoid stack-too-deep; assigns qeuro, usdc, vault, oracle, yieldShift, treasury

Notes:

  • security: Internal; only callable during init

  • validation: Addresses set by initializer

  • state-changes: Updates contract reference state

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal; only from initialize

  • oracle: None

function _setUserPoolContractReferences(
    address _qeuro,
    address _usdc,
    address _vault,
    address _oracle,
    address _yieldShift,
    address _treasury
) internal;

Parameters

NameTypeDescription
_qeuroaddressQEURO token address
_usdcaddressUSDC token address
_vaultaddressQuantillonVault address
_oracleaddressOracle address
_yieldShiftaddressYieldShift address
_treasuryaddressTreasury address

deposit

Deposit USDC to mint QEURO (unified single/batch function)

Handles both single deposits and batch deposits in one function

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Public access

  • oracle: No oracle dependencies

function deposit(uint256[] calldata usdcAmounts, uint256[] calldata minQeuroOuts)
    external
    nonReentrant
    whenNotPaused
    flashLoanProtection
    returns (uint256[] memory qeuroMintedAmounts);

Parameters

NameTypeDescription
usdcAmountsuint256[]Array of USDC amounts to deposit (6 decimals) - use [amount] for single
minQeuroOutsuint256[]Array of minimum QEURO amounts to receive (18 decimals) - use [amount] for single

Returns

NameTypeDescription
qeuroMintedAmountsuint256[]Array of QEURO amounts minted (18 decimals)

_validateAndTransferTokens

Internal function to validate amounts and transfer tokens (unified validation)

Unified validation and transfer function to reduce code duplication

Notes:

  • security: Validates all amounts > 0 before transfer

  • validation: Validates each amount in array is positive

  • state-changes: Transfers tokens from/to msg.sender

  • events: No events emitted - handled by calling function

  • errors: Throws if any amount is 0

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _validateAndTransferTokens(uint256[] calldata amounts, IERC20 token, bool isFromUser)
    internal
    returns (uint256 totalAmount);

Parameters

NameTypeDescription
amountsuint256[]Array of amounts to validate and transfer
tokenIERC20Token to transfer (usdc or qeuro)
isFromUserboolWhether to transfer from user (true) or to user (false)

Returns

NameTypeDescription
totalAmountuint256Total amount transferred

_initializeUserIfNeeded

Internal function to initialize user if needed (consolidated)

Initializes user tracking if they haven't deposited before

Notes:

  • security: Updates hasDeposited mapping and totalUsers counter

  • validation: No input validation required

  • state-changes: Updates hasDeposited[msg.sender] and totalUsers

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _initializeUserIfNeeded() internal;

_calculateNetAmounts

Internal function to calculate net amounts after fees

Calculates net amounts by subtracting deposit fees from each USDC amount

Notes:

  • security: Uses cached depositFee to prevent reentrancy

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _calculateNetAmounts(uint256[] calldata usdcAmounts)
    internal
    pure
    returns (uint256[] memory netAmounts, uint256 totalNetAmount);

Parameters

NameTypeDescription
usdcAmountsuint256[]Array of USDC amounts (6 decimals)

Returns

NameTypeDescription
netAmountsuint256[]Array of net amounts after fees (6 decimals)
totalNetAmountuint256Total net amount (6 decimals)

_processVaultMinting

Internal function to process vault minting operations

Processes vault minting operations with single vault call to avoid external calls in loop

Notes:

  • security: Uses single approval and single vault call to minimize external calls

  • validation: No input validation required - parameters pre-validated

  • state-changes: Updates qeuroMintedAmounts array with minted amounts

  • events: No events emitted - handled by calling function

  • errors: Throws if vault.mintQEURO fails

  • reentrancy: Protected by nonReentrant modifier on calling function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _processVaultMinting(
    uint256[] memory netAmounts,
    uint256[] calldata minQeuroOuts,
    uint256[] memory qeuroMintedAmounts
) internal;

Parameters

NameTypeDescription
netAmountsuint256[]Array of net amounts to mint (6 decimals)
minQeuroOutsuint256[]Array of minimum QEURO outputs (18 decimals)
qeuroMintedAmountsuint256[]Array to store minted amounts (18 decimals)

_updateUserAndPoolState

Internal function to update user and pool state

Updates user and pool state before external calls for reentrancy protection

Notes:

  • security: Updates state before external calls (CEI pattern)

  • validation: No input validation required - parameters pre-validated

  • state-changes: Updates user.depositHistory, totalDeposits

  • events: No events emitted - handled by calling function

  • errors: No errors thrown

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _updateUserAndPoolState(
    uint256[] calldata usdcAmounts,
    uint256 /* totalNetAmount */
)
    internal;

Parameters

NameTypeDescription
usdcAmountsuint256[]Array of USDC amounts (6 decimals)
<none>uint256

_transferQeuroAndEmitEvents

Internal function to transfer QEURO and emit events

Transfers QEURO to users and emits UserDeposit events

Notes:

  • security: Uses SafeERC20 for secure token transfers

  • validation: No input validation required - parameters pre-validated

  • state-changes: Transfers QEURO tokens to msg.sender

  • events: Emits UserDeposit event for each transfer

  • errors: Throws if QEURO transfer fails

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _transferQeuroAndEmitEvents(
    uint256[] calldata usdcAmounts,
    uint256[] memory qeuroMintedAmounts,
    uint256 currentTime
) internal;

Parameters

NameTypeDescription
usdcAmountsuint256[]Array of USDC amounts (6 decimals)
qeuroMintedAmountsuint256[]Array of minted QEURO amounts (18 decimals)
currentTimeuint256Current timestamp

_transferQeuroAndEmitEventsCommit

Commits batched user deposit tracking and QEURO transfers

Called via explicit self-call from _transferQeuroAndEmitEvents after read/validation phase.

Notes:

  • security: Restricted by onlySelf; executes from guarded parent flow

  • validation: Assumes upstream length and amount validation

  • state-changes: Appends to userDeposits[user]

  • events: Emits UserDeposit and UserDepositTracked

  • errors: Token transfer failures may revert

  • reentrancy: Structured CEI split with state updates before transfers

  • access: External self-call entrypoint only

  • oracle: Uses pre-cached oracle ratio input

function _transferQeuroAndEmitEventsCommit(
    address user,
    uint256[] calldata usdcAmounts,
    uint256[] calldata qeuroMintedAmounts,
    uint256 currentTime,
    uint32 oracleRatio,
    uint32 currentBlock
) external onlySelf;

Parameters

NameTypeDescription
useraddressDepositor receiving QEURO and tracked deposit entries
usdcAmountsuint256[]USDC amounts that backed each mint operation
qeuroMintedAmountsuint256[]QEURO amounts minted per entry
currentTimeuint256Timestamp persisted for each tracked deposit
oracleRatiouint32Cached oracle ratio associated with this batch
currentBlockuint32Block number snapshot associated with this batch

withdraw

Withdraw USDC by burning QEURO (unified single/batch function)

Handles both single withdrawals and batch withdrawals in one function

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Public access

  • oracle: No oracle dependencies

function withdraw(uint256[] calldata qeuroAmounts, uint256[] calldata minUsdcOuts)
    external
    nonReentrant
    whenNotPaused
    returns (uint256[] memory usdcReceivedAmounts);

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts to burn (18 decimals) - use [amount] for single
minUsdcOutsuint256[]Array of minimum USDC amounts to receive (6 decimals) - use [amount] for single

Returns

NameTypeDescription
usdcReceivedAmountsuint256[]Array of USDC amounts received (6 decimals)

_validateAndProcessBatchWithdrawal

Validates and processes batch withdrawal

Internal helper to reduce stack depth

Notes:

  • security: Validates amounts and user balances to prevent over-withdrawal

  • validation: Validates all amounts are positive and user has sufficient balance

  • state-changes: Updates user balance and processes withdrawal calculations

  • events: No events emitted - internal helper function

  • errors: Throws "Amount must be positive" if any amount is zero

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _validateAndProcessBatchWithdrawal(
    uint256[] calldata qeuroAmounts,
    uint256[] calldata minUsdcOuts,
    uint256[] memory usdcReceivedAmounts
) internal returns (uint32 oracleRatio, uint256 totalWithdrawn);

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts to withdraw
minUsdcOutsuint256[]Array of minimum USDC amounts expected
usdcReceivedAmountsuint256[]Array to store received USDC amounts

Returns

NameTypeDescription
oracleRatiouint32Oracle ratio snapshot stored with withdrawal tracking entries.
totalWithdrawnuint256Total USDC withdrawn across the batch.

_processVaultRedemptions

Processes vault redemptions for batch withdrawal

Internal helper to reduce stack depth

OPTIMIZATION: Uses single vault call with total amounts to avoid external calls in loop

NOTE: All fees are handled by QuantillonVault, not UserPool

Notes:

  • security: Validates vault redemption amounts and minimum outputs

  • validation: Validates all amounts are positive and within limits

  • state-changes: Processes vault redemptions and updates received amounts

  • events: No events emitted - internal helper function

  • errors: Throws validation errors if amounts are invalid

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _processVaultRedemptions(
    uint256[] calldata qeuroAmounts,
    uint256[] calldata minUsdcOuts,
    uint256[] memory usdcReceivedAmounts
) internal;

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts to redeem
minUsdcOutsuint256[]Array of minimum USDC amounts expected
usdcReceivedAmountsuint256[]Array to store received USDC amounts

_executeBatchTransfers

Executes final transfers and emits events for batch withdrawal

Internal helper to reduce stack depth

Notes:

  • security: Executes final token transfers and emits withdrawal events

  • validation: Validates all amounts are positive before transfer

  • state-changes: Burns QEURO tokens and transfers USDC to user

  • events: Emits Withdrawal event for each withdrawal

  • errors: Throws transfer errors if token operations fail

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _executeBatchTransfers(
    uint256[] calldata qeuroAmounts,
    uint256[] memory usdcReceivedAmounts,
    uint256 currentTime,
    uint32 oracleRatio,
    uint256 totalWithdrawn
) internal;

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts withdrawn
usdcReceivedAmountsuint256[]Array of USDC amounts received
currentTimeuint256Current timestamp for events
oracleRatiouint32Oracle ratio snapshot associated with this batch.
totalWithdrawnuint256Total USDC withdrawn across the batch.

_executeBatchTransfersCommit

Commits batched withdrawal tracking and settlement

Called from _executeBatchTransfers after calculation/read phase.

Notes:

  • security: Restricted by onlySelf; executes from guarded parent flow

  • validation: Assumes upstream amount validation and redemption processing

  • state-changes: Appends to userWithdrawals[user] and increments totalUserWithdrawals

  • events: Emits withdrawal tracking events and WithdrawalPending on fallback path

  • errors: Settlement helper may revert and route to pending withdrawal fallback

  • reentrancy: Structured CEI split with accounting before settlement interactions

  • access: External self-call entrypoint only

  • oracle: Uses pre-cached oracle ratio input

function _executeBatchTransfersCommit(BatchWithdrawalCommitPayload memory payload) external onlySelf;

Parameters

NameTypeDescription
payloadBatchWithdrawalCommitPayloadPacked commit payload with accounting and settlement inputs

_settlePendingWithdrawalCommit

Settles newly queued pending USDC for a user

Called via self-call from _executeBatchTransfersCommit; revert is caught to keep pending balance queued

Notes:

  • security: Restricted by onlySelf; called from guarded withdraw flow

  • validation: Reverts on insufficient pending balance or transfer failure

  • state-changes: Decrements pending balance for user

  • events: None

  • errors: Reverts on token transfer failure

  • reentrancy: Follows CEI with pending update before transfer

  • access: External self-call entrypoint only

  • oracle: No oracle dependencies

function _settlePendingWithdrawalCommit(address user, uint256 amount) external onlySelf;

Parameters

NameTypeDescription
useraddressRecipient address
amountuint256USDC amount to transfer

claimPendingWithdrawal

Claim USDC that could not be transferred during withdrawal (e.g. USDC blacklist)

Allows users to pull USDC that was queued in pendingUsdcWithdrawals after a failed transfer

Notes:

  • security: Protected by nonReentrant and whenNotPaused; only claims caller’s own pending balance

  • validation: Reverts if the caller has no pending USDC balance to claim

  • state-changes: Sets pendingUsdcWithdrawals[msg.sender] to zero and transfers USDC to the caller

  • events: Emits PendingWithdrawalClaimed with the claimed amount

  • errors: Reverts with InsufficientBalance if amount is zero

  • reentrancy: Protected by nonReentrant; uses SafeERC20 for token transfer

  • access: Public function callable by any user for their own pending withdrawal

  • oracle: No oracle dependencies

function claimPendingWithdrawal() external nonReentrant whenNotPaused;

stake

Stakes QEURO tokens (unified single/batch function)

Handles both single stakes and batch stakes in one function

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Public access

  • oracle: No oracle dependencies

function stake(uint256[] calldata qeuroAmounts) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts to stake (18 decimals) - use [amount] for single

requestUnstake

Requests to unstake QEURO tokens (starts unstaking cooldown period)

Begins the unstaking process with a cooldown period before tokens can be withdrawn

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Public access

  • oracle: No oracle dependencies

function requestUnstake(uint256 qeuroAmount) external nonReentrant;

Parameters

NameTypeDescription
qeuroAmountuint256The amount of staked QEURO tokens to unstake (18 decimals)

unstake

Complete unstaking after cooldown period

This function allows users to complete their unstaking request after the cooldown period has passed.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by nonReentrant modifier

  • access: Public access

  • oracle: No oracle dependencies

function unstake() external nonReentrant whenNotPaused;

_updatePendingRewards

Update pending rewards for a user

This internal function calculates and updates the pending rewards for a given user based on their staked amount and the current APY. Uses block-based calculations to prevent timestamp manipulation.

Notes:

  • security: Uses block-based calculations to prevent timestamp manipulation

  • validation: Validates user has staked amount > 0

  • state-changes: Updates user.pendingRewards, user.lastStakeTime, userLastRewardBlock

  • events: No events emitted - handled by calling function

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _updatePendingRewards(address user, uint256 currentTime) internal;

Parameters

NameTypeDescription
useraddressAddress of the user to update
currentTimeuint256Current timestamp for reward calculations

getUserInfo

Get comprehensive user information (consolidated view function)

Returns all user-related data in one call to reduce contract size

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getUserInfo(address user)
    external
    view
    returns (
        uint256 qeuroBalance,
        uint256 stakedAmount,
        uint256 pendingRewards,
        uint256 depositHistory,
        uint256 lastStakeTime,
        uint256 unstakeAmount,
        uint256 unstakeRequestTime
    );

Parameters

NameTypeDescription
useraddressAddress of the user to query

Returns

NameTypeDescription
qeuroBalanceuint256QEURO balance of the user (18 decimals)
stakedAmountuint256Current staked amount of the user (18 decimals)
pendingRewardsuint256Total pending rewards of the user (18 decimals)
depositHistoryuint256Total historical deposits of the user (6 decimals)
lastStakeTimeuint256Timestamp of the user's last staking action
unstakeAmountuint256Amount being unstaked (18 decimals)
unstakeRequestTimeuint256Timestamp when unstaking was requested

getPoolTotals

Get comprehensive pool totals (consolidated view function)

Returns all pool totals in one call to reduce contract size

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getPoolTotals()
    external
    view
    returns (uint256 totalDeposits, uint256 totalWithdrawals, uint256 totalStakes_, uint256 totalUsers_);

Returns

NameTypeDescription
totalDepositsuint256Total USDC deposits (6 decimals)
totalWithdrawalsuint256Total QEURO withdrawals (18 decimals)
totalStakes_uint256Total QEURO staked (18 decimals)
totalUsers_uint256Total number of users

getUserDepositHistory

Get user deposit history with oracle ratios

Used for detailed analytics and audit trails

Returns complete deposit history with oracle ratios

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getUserDepositHistory(address user) external view returns (UserDepositInfo[] memory);

Parameters

NameTypeDescription
useraddressAddress of the user

Returns

NameTypeDescription
<none>UserDepositInfo[]Array of UserDepositInfo structs containing deposit history

getUserWithdrawals

Get user withdrawal history with oracle ratios

Used for detailed analytics and audit trails

Returns complete withdrawal history with oracle ratios

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getUserWithdrawals(address user) external view returns (UserWithdrawalInfo[] memory);

Parameters

NameTypeDescription
useraddressAddress of the user

Returns

NameTypeDescription
<none>UserWithdrawalInfo[]Array of UserWithdrawalInfo structs containing withdrawal history

_getOracleRatioScaled

Get current oracle EUR/USD ratio scaled down for compact storage

Used internally for tracking oracle ratios in deposit/withdrawal records. Supports both 18-decimal prices (production IOracle) and 8-decimal prices (legacy mocks) by normalizing to an 8-decimal representation before scaling down by 1e6.

Notes:

  • security: No direct security implications – read-only helper

  • validation: Reverts if the underlying oracle reports an invalid price

  • state-changes: No state changes – internal helper

  • events: No events emitted

  • errors: Reverts with InvalidOraclePrice if isValid is false

  • reentrancy: No external stateful calls besides the oracle read

  • access: Internal function

  • oracle: Depends on IOracle.getEurUsdPrice for the current EUR/USD rate

function _getOracleRatioScaled() internal returns (uint32);

Returns

NameTypeDescription
<none>uint32Oracle ratio scaled to two decimals (e.g., 1.08 EUR/USD becomes 108)

getTotalDeposits

Get the total USDC equivalent withdrawals across all users

Get the current user pool size in USDC terms

Used for analytics and cash flow monitoring

Returns current QEURO supply converted to USDC using the read-only oracle details path. totalUserDeposits is cumulative analytics state and is not a live pool-size metric.

Notes:

  • access: Public access

  • oracle: No oracle dependencies

  • security: Uses validated oracle details and reverts on stale or out-of-bounds prices

  • validation: Reverts if the oracle price cannot support a current TVL metric

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Throws InvalidOraclePrice when oracle details are stale, invalid, or zero

  • reentrancy: Not applicable - view function

  • access: Public access

  • oracle: Requires fresh read-only EUR/USD oracle details

function getTotalDeposits() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total withdrawals in USDC equivalent (6 decimals)

getTotalStakes

Get the total QEURO staked across all users

Returns the total amount of QEURO currently staked in the pool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getTotalStakes() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total QEURO staked (18 decimals)

getPoolMetrics

Get various metrics about the user pool

Returns comprehensive pool statistics including user count, averages, and ratios

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPoolMetrics()
    external
    view
    returns (uint256 totalUsers_, uint256 averageDeposit, uint256 stakingRatio, uint256 poolTVL);

Returns

NameTypeDescription
totalUsers_uint256Number of unique users
averageDeposituint256Average deposit amount per user (6 decimals)
stakingRatiouint256Ratio of total staked QEURO to total deposits (basis points)
poolTVLuint256Total value locked in the pool (6 decimals)

getPoolAnalytics

Get comprehensive pool analytics using QEURO total supply

Uses QEURO total supply for accurate analytics instead of misleading USDC tracking

Notes:

  • security: No external calls except oracle, read-only function

  • validation: Oracle price validation with fallback to zero

  • state-changes: No state changes, view-like function

  • events: No events emitted

  • errors: No custom errors, handles oracle failures gracefully

  • reentrancy: No reentrancy risk, read-only operations

  • access: Public access

  • oracle: Requires fresh oracle price data for USDC equivalent

function getPoolAnalytics()
    external
    returns (
        uint256 currentQeuroSupply,
        uint256 usdcEquivalentAtCurrentRate,
        uint256 totalUsers_,
        uint256 totalStakes_
    );

Returns

NameTypeDescription
currentQeuroSupplyuint256Current QEURO total supply (net minted QEURO)
usdcEquivalentAtCurrentRateuint256Current USDC equivalent of QEURO supply
totalUsers_uint256Total number of users
totalStakes_uint256Total QEURO staked

getPoolConfiguration

Get comprehensive pool configuration (consolidated view function)

Returns all pool configuration parameters in one call to reduce contract size

NOTE: Mint/redemption fees are handled by QuantillonVault, not UserPool

Notes:

  • security: No security implications (view function)

  • validation: No validation required

  • state-changes: No state changes (view function)

  • events: No events (view function)

  • errors: No custom errors

  • reentrancy: No external calls, safe

  • access: Public (anyone can call)

  • oracle: No oracle dependencies

function getPoolConfiguration()
    external
    view
    returns (
        uint256 stakingAPY_,
        uint256 depositAPY_,
        uint256 minStakeAmount_,
        uint256 unstakingCooldown_,
        uint256 performanceFee_
    );

Returns

NameTypeDescription
stakingAPY_uint256Current staking APY in basis points
depositAPY_uint256Current deposit APY in basis points
minStakeAmount_uint256Current minimum stake amount (18 decimals)
unstakingCooldown_uint256Current unstaking cooldown period (seconds)
performanceFee_uint256Current performance fee on staking rewards (basis points)

calculateProjectedRewards

Calculate projected rewards for a given QEURO amount and duration

Calculates the expected rewards for staking a specific amount for a given duration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function calculateProjectedRewards(uint256 qeuroAmount, uint256 duration) external view returns (uint256);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to calculate rewards for (18 decimals)
durationuint256Duration in seconds

Returns

NameTypeDescription
<none>uint256uint256 Calculated rewards (18 decimals)

updateStakingParameters

Update the parameters for staking (APY, min stake, cooldown)

This function is restricted to governance roles.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateStakingParameters(uint256 newStakingAPY, uint256 newMinStakeAmount, uint256 newUnstakingCooldown)
    external
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newStakingAPYuint256New Staking APY in basis points
newMinStakeAmountuint256New Minimum stake amount (18 decimals)
newUnstakingCooldownuint256New unstaking cooldown period (seconds)

setPerformanceFee

Set the performance fee for staking rewards

This function is restricted to governance roles.

NOTE: Mint/redemption fees are set in QuantillonVault, not UserPool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates performanceFee <= 2000 bps (20%)

  • state-changes: Updates performanceFee state variable

  • events: None

  • errors: Reverts if fee exceeds maximum allowed

  • reentrancy: Not applicable

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: Not applicable

function setPerformanceFee(uint256 _performanceFee) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_performanceFeeuint256New performance fee on staking rewards in basis points

updateYieldShift

Updates the YieldShift contract address

Governance-only setter for phased deployment wiring

Notes:

  • security: Restricted to governance; validates non-zero address

  • validation: Ensures _yieldShift is not the zero address

  • state-changes: Updates the yieldShift integration reference

  • events: None

  • errors: Reverts with "token" validation error on zero address

  • reentrancy: Not applicable

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: Not applicable

function updateYieldShift(address _yieldShift) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_yieldShiftaddressNew YieldShift contract address

emergencyUnstake

Emergency unstake for a specific user (restricted to emergency roles)

Forcibly unstakes a user’s full staked balance and sends it to the specified recipient

Notes:

  • security: Restricted to EMERGENCY_ROLE to prevent arbitrary unstaking

  • validation: If recipient is address(0) it is automatically replaced with user

  • state-changes: Sets userdata.stakedAmount to zero and decreases totalStakes by the unstaked amount

  • events: Emits no specific event; external monitoring should rely on QEURO transfers

  • errors: No custom errors; function is a best-effort emergency escape hatch

  • reentrancy: Protected by onlyRole but not nonReentrant; single SafeERC20 transfer at the end

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function emergencyUnstake(address user, address recipient) external onlyRole(EMERGENCY_ROLE);

Parameters

NameTypeDescription
useraddressAddress of the user whose staked QEURO will be unstaked
recipientaddressAddress that will receive the unstaked QEURO (defaults to user when zero)

pause

Pause the user pool (restricted to emergency roles)

This function is used to pause critical operations in case of a protocol-wide emergency or vulnerability.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpause the user pool (restricted to emergency roles)

This function is used to re-enable critical operations after an emergency pause.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external onlyRole(EMERGENCY_ROLE);

isPoolActive

Check if the user pool is currently active (not paused)

Returns the current pause status of the pool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isPoolActive() external view returns (bool);

Returns

NameTypeDescription
<none>boolbool True if the pool is active, false otherwise

recoverToken

Recover accidentally sent tokens to treasury only

Recovers accidentally sent ERC20 tokens to the treasury address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

executeWithQuote

Dispatch one signed operation with the original caller and existing accounting.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function executeWithQuote(bytes calldata callData, bytes calldata authorization)
    external
    whenNotPaused
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

Events

UserDeposit

Emitted when a user deposits USDC and receives QEURO

Indexed parameters allow efficient filtering of events

event UserDeposit(address indexed user, uint256 usdcAmount, uint256 qeuroMinted, uint256 timestamp);

Parameters

NameTypeDescription
useraddressAddress of the user who deposited
usdcAmountuint256Amount of USDC deposited (6 decimals)
qeuroMinteduint256Amount of QEURO minted (18 decimals)
timestampuint256Timestamp of the deposit

UserWithdrawal

Emitted when a user withdraws QEURO and receives USDC

Indexed parameters allow efficient filtering of events

event UserWithdrawal(address indexed user, uint256 qeuroBurned, uint256 usdcReceived, uint256 timestamp);

Parameters

NameTypeDescription
useraddressAddress of the user who withdrew
qeuroBurneduint256Amount of QEURO burned (18 decimals)
usdcReceiveduint256Amount of USDC received (6 decimals)
timestampuint256Timestamp of the withdrawal

UserDepositTracked

Emitted when a user deposit is tracked with oracle ratio

event UserDepositTracked(
    address indexed user,
    uint256 usdcAmount,
    uint256 qeuroReceived,
    uint256 oracleRatio,
    uint256 timestamp,
    uint256 blockNumber
);

Parameters

NameTypeDescription
useraddressAddress of the user who deposited
usdcAmountuint256USDC amount deposited (6 decimals)
qeuroReceiveduint256QEURO amount received (18 decimals)
oracleRatiouint256Oracle ratio at time of deposit (scaled by 1e6)
timestampuint256Block timestamp when deposit was made
blockNumberuint256Block number when deposit was made

UserWithdrawalTracked

Emitted when a user withdrawal is tracked with oracle ratio

event UserWithdrawalTracked(
    address indexed user,
    uint256 qeuroAmount,
    uint256 usdcReceived,
    uint256 oracleRatio,
    uint256 timestamp,
    uint256 blockNumber
);

Parameters

NameTypeDescription
useraddressAddress of the user who withdrew
qeuroAmountuint256QEURO amount withdrawn (18 decimals)
usdcReceiveduint256USDC amount received (6 decimals)
oracleRatiouint256Oracle ratio at time of withdrawal (scaled by 1e6)
timestampuint256Block timestamp when withdrawal was made
blockNumberuint256Block number when withdrawal was made

WithdrawalPending

Emitted when a USDC transfer to a user fails (e.g. USDC blacklist) and is queued

event WithdrawalPending(address indexed user, uint256 amount);

PendingWithdrawalClaimed

Emitted when a user claims their pending USDC withdrawal

event PendingWithdrawalClaimed(address indexed user, uint256 amount);

QEUROStaked

Emitted when a user stakes QEURO

Indexed parameters allow efficient filtering of events

event QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 timestamp);

Parameters

NameTypeDescription
useraddressAddress of the user who staked
qeuroAmountuint256Amount of QEURO staked (18 decimals)
timestampuint256Timestamp of the staking action

QEUROUnstaked

Emitted when a user unstakes QEURO

Indexed parameters allow efficient filtering of events

event QEUROUnstaked(address indexed user, uint256 qeuroAmount, uint256 timestamp);

Parameters

NameTypeDescription
useraddressAddress of the user who unstaked
qeuroAmountuint256Amount of QEURO unstaked (18 decimals)
timestampuint256Timestamp of the unstaking action

PoolParameterUpdated

Emitted when pool parameters are updated

OPTIMIZED: Indexed parameter name for efficient filtering by parameter type

event PoolParameterUpdated(string indexed parameter, uint256 oldValue, uint256 newValue);

Parameters

NameTypeDescription
parameterstringName of the parameter updated
oldValueuint256Original value of the parameter
newValueuint256New value of the parameter

ETHRecovered

Emitted when ETH is recovered to the treasury

event ETHRecovered(address indexed to, uint256 indexed amount);

Parameters

NameTypeDescription
toaddressRecipient address
amountuint256Amount of ETH recovered

Structs

UserInfo

User information data structure

Stores all information about a user's deposits, stakes, and rewards

Used for user management and reward calculations

OPTIMIZED: Timestamps and amounts packed for gas efficiency

struct UserInfo {
    uint128 qeuroBalance; // QEURO balance from deposits (18 decimals, max ~340B)
    uint128 stakedAmount; // QEURO amount currently staked (18 decimals, max ~340B)
    uint128 pendingRewards; // Pending staking rewards in QEURO (18 decimals, max ~340B)
    uint128 unstakeAmount; // Amount being unstaked (18 decimals, max ~340B)
    uint96 depositHistory; // Total historical deposits in USDC (6 decimals, max ~79B USDC)
    uint64 lastStakeTime; // Timestamp of last staking action (until year 2554)
    uint64 unstakeRequestTime; // Timestamp when unstaking was requested (until year 2554)
}

UserDepositInfo

User deposit information with oracle ratio tracking

Stores individual deposit records with oracle ratios for detailed analytics

Used for audit trails and historical analysis

struct UserDepositInfo {
    uint128 usdcAmount; // USDC amount deposited (6 decimals, max ~340B USDC)
    uint128 qeuroReceived; // QEURO amount received (18 decimals, max ~340B QEURO)
    uint64 timestamp; // Block timestamp when deposit was made (until year 2554)
    uint32 oracleRatio; // Oracle ratio at time of deposit (scaled by 1e6, max ~4.2B)
    uint32 blockNumber; // Block number when deposit was made (until year 2106)
}

UserWithdrawalInfo

User withdrawal information with oracle ratio tracking

Stores individual withdrawal records with oracle ratios for detailed analytics

Used for audit trails and historical analysis

struct UserWithdrawalInfo {
    uint128 qeuroAmount; // QEURO amount withdrawn (18 decimals, max ~340B QEURO)
    uint128 usdcReceived; // USDC amount received (6 decimals, max ~340B USDC)
    uint64 timestamp; // Block timestamp when withdrawal was made (until year 2554)
    uint32 oracleRatio; // Oracle ratio at time of withdrawal (scaled by 1e6, max ~4.2B)
    uint32 blockNumber; // Block number when withdrawal was made (until year 2106)
}

BatchWithdrawalCommitPayload

Packed payload used to commit batch withdrawal accounting and settlement.

struct BatchWithdrawalCommitPayload {
    address user;
    uint256[] qeuroAmounts;
    uint256[] usdcReceivedAmounts;
    uint256 currentTime;
    uint32 oracleRatio;
    uint32 currentBlock;
    uint256 totalWithdrawn;
}

stQEUROFactory

Git Source

Inherits: Initializable, AccessControlUpgradeable, SecureUpgradeable, IVersioned

Title: stQEUROFactory

Deploys and registers one stQEURO token proxy per staking vault.

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_FACTORY_ROLE

bytes32 public constant VAULT_FACTORY_ROLE = keccak256("VAULT_FACTORY_ROLE")

State Variables

tokenImplementation

stQEUROToken implementation used by newly deployed ERC1967 proxies.

address public tokenImplementation

qeuro

address public qeuro

yieldShift

address public yieldShift

usdc

address public usdc

treasury

address public treasury

oracle

address public oracle

tokenAdmin

address public tokenAdmin

stQEUROByVaultId

mapping(uint256 => address) public stQEUROByVaultId

stQEUROByVault

mapping(address => address) public stQEUROByVault

vaultById

mapping(uint256 => address) public vaultById

vaultIdByStQEURO

mapping(address => uint256) public vaultIdByStQEURO

_vaultIdsByVault

mapping(address => uint256[]) private _vaultIdsByVault

_vaultNamesById

mapping(uint256 => string) private _vaultNamesById

_vaultNameHashUsed

mapping(bytes32 => bool) private _vaultNameHashUsed

vaultNameHashesMigrated

Whether content-based hashes have been backfilled for all registered vault names.

bool public vaultNameHashesMigrated

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Disables initializers on the implementation contract.

Prevents direct initialization of the logic contract in proxy deployments.

Notes:

  • security: Locks implementation initialization to prevent takeover.

  • validation: No input parameters.

  • state-changes: Sets initializer state to disabled.

  • events: No events emitted.

  • errors: No custom errors expected.

  • reentrancy: Not applicable during construction.

  • access: Constructor executes once at deployment.

  • oracle: No oracle dependencies.

constructor() ;

initialize

Initializes the stQEURO factory configuration and roles.

Sets deployment dependencies and grants admin/governance/factory roles to admin.

Notes:

  • security: Validates all critical addresses before storing configuration.

  • validation: Reverts on zero addresses for required dependencies.

  • state-changes: Initializes access control and stores factory dependencies.

  • events: Emits role grant events from AccessControl initialization.

  • errors: Reverts with custom invalid-address errors for bad inputs.

  • reentrancy: Protected by initializer pattern; no external untrusted flow.

  • access: Callable once via initializer.

  • oracle: Stores oracle configuration address; no live price reads.

function initialize(
    address admin,
    address _tokenImplementation,
    address _qeuro,
    address _yieldShift,
    address _usdc,
    address _treasury,
    address _timelock,
    address _oracle
) external initializer;

Parameters

NameTypeDescription
adminaddressAddress receiving admin and governance privileges.
_tokenImplementationaddressERC1967 implementation used for new stQEURO proxies.
_qeuroaddressQEURO token address.
_yieldShiftaddressYieldShift contract address.
_usdcaddressUSDC token address.
_treasuryaddressTreasury address used by deployed tokens.
_timelockaddressTimelock contract used by SecureUpgradeable.
_oracleaddressOracle address referenced by the factory configuration.

initializeVaultNameHashesV2

Backfills content-based vault-name hashes after a factory implementation upgrade.

Runs once through reinitializer(2), hashing each supplied registered name before enabling registration.

Notes:

  • security: Governance-only migration; registration remains disabled until it completes.

  • validation: Requires every id to be registered and the list to be strictly increasing.

  • state-changes: Reserves each existing name hash and enables future registrations.

  • events: Emits initializer framework events where applicable.

  • errors: Reverts for an already completed migration, invalid ordering, or unknown vault ids.

  • reentrancy: No external calls.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function initializeVaultNameHashesV2(uint256[] calldata vaultIds)
    external
    onlyRole(GOVERNANCE_ROLE)
    reinitializer(2);

Parameters

NameTypeDescription
vaultIdsuint256[]Complete, strictly increasing list of registered vault identifiers.

registerVault

Strict self-registration entrypoint. Caller vault deploys its own stQEURO.

Computes deterministic proxy address, commits registry state, then deploys proxy with CREATE2.

Notes:

  • security: Restricts calls to VAULT_FACTORY_ROLE and enforces single-registration invariants.

  • validation: Validates non-zero vault id, caller uniqueness, and vault name format.

  • state-changes: Writes vault/token registry mappings and vault name tracking.

  • events: Emits VaultRegistered on successful registration.

  • errors: Reverts on invalid input, duplicate registration, or unexpected deployment address.

  • reentrancy: Uses deterministic CEI ordering; critical state is committed before proxy deployment.

  • access: Restricted to VAULT_FACTORY_ROLE.

  • oracle: No oracle dependencies.

function registerVault(uint256 vaultId, string calldata vaultName)
    external
    onlyRole(VAULT_FACTORY_ROLE)
    returns (address stQEUROToken_);

Parameters

NameTypeDescription
vaultIduint256Unique vault identifier in factory registry.
vaultNamestringUppercase alphanumeric vault label used for token metadata.

Returns

NameTypeDescription
stQEUROToken_addressDeterministic stQEURO proxy address registered for the vault.

previewVaultToken

Previews the deterministic stQEURO token address for a vault registration.

Computes the CREATE2 address using current factory configuration and provided vault metadata.

Notes:

  • security: Read-only helper for deterministic address binding before registration.

  • validation: Reverts for zero vault address, zero vault id, or invalid vault name.

  • state-changes: No state changes; pure preview path.

  • events: No events emitted.

  • errors: Reverts on invalid vault metadata.

  • reentrancy: Not applicable for view function.

  • access: Public view helper.

  • oracle: No oracle dependencies.

function previewVaultToken(address vault, uint256 vaultId, string calldata vaultName)
    external
    view
    returns (address stQEUROToken_);

Parameters

NameTypeDescription
vaultaddressVault contract address that will call registerVault.
vaultIduint256Target vault identifier.
vaultNamestringUppercase alphanumeric vault label.

Returns

NameTypeDescription
stQEUROToken_addressPredicted stQEURO proxy address for this registration tuple.

getStQEUROByVaultId

Returns registered stQEURO token by vault id.

Reads factory mapping for vault-id-to-token resolution.

Notes:

  • security: Read-only lookup with no privileged behavior.

  • validation: No additional validation; returns zero for unknown ids.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getStQEUROByVaultId(uint256 vaultId) external view returns (address stQEUROToken_);

Parameters

NameTypeDescription
vaultIduint256Vault identifier in factory registry.

Returns

NameTypeDescription
stQEUROToken_addressRegistered stQEURO token address (or zero if unset).

getVaultIdsByVault

Returns all vault ids registered by a vault contract.

A single QuantillonVault instance can register multiple vault ids.

Notes:

  • security: Read-only registry accessor.

  • validation: No additional validation; unknown vaults return an empty array.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultIdsByVault(address vault) external view returns (uint256[] memory vaultIds);

Parameters

NameTypeDescription
vaultaddressVault contract address.

Returns

NameTypeDescription
vaultIdsuint256[]Array of registered vault ids for vault.

getVaultById

Returns vault address bound to a vault id.

Reads registry mapping populated during registration.

Notes:

  • security: Read-only lookup.

  • validation: No additional validation; returns zero for unknown ids.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultById(uint256 vaultId) external view returns (address vault);

Parameters

NameTypeDescription
vaultIduint256Vault identifier in factory registry.

Returns

NameTypeDescription
vaultaddressVault address associated with the id (or zero if unset).

getVaultIdByStQEURO

Returns vault id bound to an stQEURO token.

Reads reverse registry mapping from token address to vault id.

Notes:

  • security: Read-only lookup.

  • validation: No additional validation; returns zero for unknown tokens.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultIdByStQEURO(address stQEUROToken_) external view returns (uint256 vaultId);

Parameters

NameTypeDescription
stQEUROToken_addressRegistered stQEURO token address.

Returns

NameTypeDescription
vaultIduint256Vault identifier associated with the token (or zero if unset).

getVaultName

Returns vault name string for a vault id.

Reads the stored canonical vault label registered at creation time.

Notes:

  • security: Read-only lookup.

  • validation: No additional validation; returns empty value for unknown ids.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultName(uint256 vaultId) external view returns (string memory vaultName);

Parameters

NameTypeDescription
vaultIduint256Vault identifier in factory registry.

Returns

NameTypeDescription
vaultNamestringStored vault name (empty string if unset).

updateYieldShift

Updates YieldShift dependency for future token deployments.

Governance-only setter for the factory-level YieldShift address.

Notes:

  • security: Restricted to governance role.

  • validation: Reverts if _yieldShift is zero address.

  • state-changes: Updates yieldShift configuration.

  • events: Emits FactoryConfigUpdated.

  • errors: Reverts with InvalidToken for zero address.

  • reentrancy: No external calls beyond event emission.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function updateYieldShift(address _yieldShift) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_yieldShiftaddressNew YieldShift contract address.

updateTokenImplementation

Updates stQEURO implementation used for new proxies.

Governance-only setter for proxy implementation address.

Notes:

  • security: Restricted to governance role.

  • validation: Reverts if _tokenImplementation is zero address.

  • state-changes: Updates tokenImplementation configuration.

  • events: Emits FactoryConfigUpdated.

  • errors: Reverts with InvalidToken for zero address.

  • reentrancy: No external calls beyond event emission.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function updateTokenImplementation(address _tokenImplementation) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_tokenImplementationaddressNew implementation contract address.

updateOracle

Updates oracle dependency address for factory configuration.

Governance-only setter for oracle address used by future deployments.

Notes:

  • security: Restricted to governance role.

  • validation: Reverts if _oracle is zero address.

  • state-changes: Updates oracle configuration.

  • events: Emits FactoryConfigUpdated.

  • errors: Reverts with InvalidOracle for zero address.

  • reentrancy: No external calls beyond event emission.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Updates oracle reference; no live price reads.

function updateOracle(address _oracle) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_oracleaddressNew oracle contract address.

updateTreasury

Updates treasury address propagated to new token deployments.

Governance-only setter for factory treasury configuration.

Notes:

  • security: Restricted to governance role.

  • validation: Reverts if _treasury is zero address.

  • state-changes: Updates treasury configuration.

  • events: Emits FactoryConfigUpdated.

  • errors: Reverts with InvalidTreasury for zero address.

  • reentrancy: No external calls beyond event emission.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function updateTreasury(address _treasury) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address.

updateTokenAdmin

Updates token admin propagated to new token deployments.

Governance-only setter for default token admin address.

Notes:

  • security: Restricted to governance role.

  • validation: Reverts if _tokenAdmin is zero address.

  • state-changes: Updates tokenAdmin configuration.

  • events: Emits FactoryConfigUpdated.

  • errors: Reverts with InvalidAdmin for zero address.

  • reentrancy: No external calls beyond event emission.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function updateTokenAdmin(address _tokenAdmin) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_tokenAdminaddressNew admin address for newly deployed stQEURO proxies.

_validateVaultName

Validates vault name format used by the registry.

Accepts only uppercase letters and digits with length in range 1..12.

Notes:

  • security: Prevents malformed identifiers from entering registry state.

  • validation: Reverts for empty, oversized, or non-alphanumeric-uppercase names.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with InvalidParameter on invalid name format.

  • reentrancy: Not applicable for pure validation helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _validateVaultName(string calldata vaultName) internal pure;

Parameters

NameTypeDescription
vaultNamestringCandidate vault label to validate.

_vaultSalt

Computes deterministic CREATE2 salt for vault registration.

Hashes vault identity tuple to ensure unique deterministic deployment address.

Notes:

  • security: Deterministic salt prevents accidental collisions across registrations.

  • validation: Expects validated inputs from caller functions.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for pure helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _vaultSalt(address vault, uint256 vaultId, string calldata vaultName)
    internal
    pure
    returns (bytes32 salt);

Parameters

NameTypeDescription
vaultaddressVault contract address.
vaultIduint256Vault identifier.
vaultNamestringVault name string.

Returns

NameTypeDescription
saltbytes32CREATE2 salt derived from vault tuple.

_buildInitData

Builds initializer calldata for stQEURO proxy deployment.

Encodes token metadata and dependency addresses for the stQEURO initialize call.

Notes:

  • security: Uses factory-stored trusted dependency addresses.

  • validation: Expects validated vault name input from caller.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No custom errors expected.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: Uses stored oracle address indirectly through configuration.

function _buildInitData(string calldata vaultName) internal view returns (bytes memory initData);

Parameters

NameTypeDescription
vaultNamestringVault name used to derive token display name and symbol.

Returns

NameTypeDescription
initDatabytesABI-encoded initializer payload for proxy constructor.

_predictProxyAddress

Predicts CREATE2 proxy address for a vault registration.

Recreates ERC1967Proxy creation bytecode hash and computes deterministic deployment address.

Notes:

  • security: Enables pre-commit address binding to mitigate registration race inconsistencies.

  • validation: Expects valid creation inputs from caller.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No custom errors expected.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _predictProxyAddress(bytes32 salt, bytes memory initData) internal view returns (address);

Parameters

NameTypeDescription
saltbytes32CREATE2 salt for deployment.
initDatabytesABI-encoded initializer payload.

Returns

NameTypeDescription
<none>addressPredicted proxy address for the given deployment inputs.

Events

VaultRegistered

event VaultRegistered(
    uint256 indexed vaultId, address indexed vault, address indexed stQEUROToken, string vaultName
);

FactoryConfigUpdated

event FactoryConfigUpdated(string indexed key, address oldValue, address newValue);

stQEUROToken

Git Source

Inherits: Initializable, ERC4626Upgradeable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, SecureUpgradeable, IVersioned

Title: stQEUROToken

ERC-4626 vault over QEURO used for per-vault staking series.

Constants

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

VIRTUAL_SHARES

uint256 private constant VIRTUAL_SHARES = 1e12

TIME_PROVIDER

TimeProvider public immutable TIME_PROVIDER

State Variables

qeuro

IQEUROToken public qeuro

treasury

address public treasury

vaultName

string public vaultName

yieldFee

uint256 public yieldFee

accountedBalance

uint256 private accountedBalance

unvestedBalance

uint256 private unvestedBalance

vestingEnd

uint64 private vestingEnd

lastVestingUpdate

uint64 private lastVestingUpdate

vestingPeriod

uint32 public vestingPeriod

vestingInitialized

bool private vestingInitialized

virtualAssets

uint256 private virtualAssets

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructs the implementation contract with its immutable time provider.

Validates the provided time provider, stores it immutably, and disables initializers on the implementation.

Notes:

  • security: Rejects zero-address dependencies before deployment completes.

  • validation: Ensures _TIME_PROVIDER is non-zero.

  • state-changes: Sets the immutable TIME_PROVIDER reference and disables future initializers on the implementation.

  • events: None.

  • errors: Reverts with ZeroAddress when _TIME_PROVIDER is the zero address.

  • reentrancy: Not applicable.

  • access: Deployment only.

  • oracle: Not applicable.

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderTime provider used by inherited secure upgrade and timelock logic.

_protocolTime

Returns canonical protocol time from this contract's TimeProvider

Overrides the SecureUpgradeable base, which returns block.timestamp.

Notes:

  • security: Reads the immutable TimeProvider set at construction

  • validation: None required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Canonical protocol time in seconds

initialize

Initializes the default stQEURO vault series without a vault suffix.

Keeps the legacy initializer shape for factory compatibility, ignores unused placeholder addresses, and wires the ERC-4626 vault over QEURO.

Notes:

  • security: Uses OpenZeppelin initializer guards and validates all named dependencies before role grants.

  • validation: Ensures admin, token, treasury, and timelock dependencies are valid for vault setup.

  • state-changes: Initializes ERC-20/ERC-4626 metadata, role assignments, treasury configuration, and the vault asset reference.

  • events: Emits initialization events through inherited OpenZeppelin modules when applicable.

  • errors: Reverts on duplicate initialization or invalid dependency addresses.

  • reentrancy: Not applicable during initialization.

  • access: Callable once during deployment.

  • oracle: Not applicable.

function initialize(address admin, address _qeuro, address, address, address _treasury, address _timelock)
    public
    initializer;

Parameters

NameTypeDescription
adminaddressAddress receiving admin, governance, and emergency roles.
_qeuroaddressQEURO token used as the ERC-4626 underlying asset.
<none>address
<none>address
_treasuryaddressTreasury that receives recovered assets and fees.
_timelockaddressTimelock used by inherited secure upgrade controls.

initialize

Initializes a vault-specific stQEURO series with custom metadata.

Builds vault-specific ERC-20 metadata, sets the ERC-4626 asset to QEURO, and applies secure-role configuration.

Notes:

  • security: Uses initializer guards and validates critical dependency addresses before activation.

  • validation: Ensures named dependencies are non-zero and treasury configuration is valid.

  • state-changes: Initializes ERC-20/ERC-4626 metadata, stores vaultName, and grants operational roles.

  • events: Emits initialization events through inherited OpenZeppelin modules when applicable.

  • errors: Reverts on duplicate initialization or invalid dependency addresses.

  • reentrancy: Not applicable during initialization.

  • access: Callable once during deployment.

  • oracle: Not applicable.

function initialize(address admin, address _qeuro, address _treasury, address _timelock, string calldata _vaultName)
    public
    initializer;

Parameters

NameTypeDescription
adminaddressAddress receiving admin, governance, and emergency roles.
_qeuroaddressQEURO token used as the ERC-4626 underlying asset.
_treasuryaddressTreasury that receives recovered assets and fees.
_timelockaddressTimelock used by inherited secure upgrade controls.
_vaultNamestringVault suffix appended to the share-token name and symbol.

_initializeStQEURODependencies

Applies the shared dependency and role setup for all stQEURO vault series.

Initializes inherited access-control, pause, reentrancy, and secure-upgrade modules, then stores treasury and QEURO references.

Notes:

  • security: Centralizes all critical dependency validation before privileged roles are granted.

  • validation: Requires non-zero admin/token/treasury addresses and a valid treasury destination.

  • state-changes: Initializes inherited modules, grants roles, stores token/treasury references, and resets yieldFee to zero.

  • events: Emits inherited role/admin initialization events when applicable.

  • errors: Reverts on invalid addresses or treasury configuration failures.

  • reentrancy: Not applicable.

  • access: Internal initialization helper.

  • oracle: Not applicable.

function _initializeStQEURODependencies(
    address admin,
    address qeuroAddress,
    address treasuryAddress,
    address timelockAddress
) internal;

Parameters

NameTypeDescription
adminaddressAddress receiving admin, governance, and emergency roles.
qeuroAddressaddressAddress of the QEURO underlying asset.
treasuryAddressaddressTreasury destination for recovered funds.
timelockAddressaddressTimelock used by the inherited secure-upgrade module.

maxDeposit

Returns the maximum assets a receiver can deposit while respecting pause state.

Returns zero when the vault is paused and otherwise delegates limit calculation to the ERC-4626 parent implementation.

Notes:

  • security: Read-only helper.

  • validation: Paused state forces a zero limit.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function maxDeposit(address receiver) public view override returns (uint256);

Parameters

NameTypeDescription
receiveraddressAddress that would receive minted stQEURO shares.

Returns

NameTypeDescription
<none>uint256maxAssets Maximum QEURO assets currently depositable for receiver.

maxMint

Returns the maximum shares a receiver can mint while respecting pause state.

Returns zero when the vault is paused and otherwise delegates limit calculation to the ERC-4626 parent implementation.

Notes:

  • security: Read-only helper.

  • validation: Paused state forces a zero limit.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function maxMint(address receiver) public view override returns (uint256);

Parameters

NameTypeDescription
receiveraddressAddress that would receive minted stQEURO shares.

Returns

NameTypeDescription
<none>uint256maxShares Maximum stQEURO shares currently mintable for receiver.

maxWithdraw

Returns the maximum assets an owner can withdraw while respecting pause state.

Returns zero when the vault is paused and otherwise delegates limit calculation to the ERC-4626 parent implementation.

Notes:

  • security: Read-only helper.

  • validation: Paused state forces a zero limit.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function maxWithdraw(address owner) public view override returns (uint256);

Parameters

NameTypeDescription
owneraddressShare owner whose withdraw capacity is being queried.

Returns

NameTypeDescription
<none>uint256maxAssets Maximum QEURO assets currently withdrawable by owner.

maxRedeem

Returns the maximum shares an owner can redeem while respecting pause state.

Returns zero when the vault is paused and otherwise delegates limit calculation to the ERC-4626 parent implementation.

Notes:

  • security: Read-only helper.

  • validation: Paused state forces a zero limit.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function maxRedeem(address owner) public view override returns (uint256);

Parameters

NameTypeDescription
owneraddressShare owner whose redeem capacity is being queried.

Returns

NameTypeDescription
<none>uint256maxShares Maximum stQEURO shares currently redeemable by owner.

totalAssets

Returns only principal and the currently vested portion of yield.

Unvested underlying remains excluded from ERC-4626 share pricing.

Notes:

  • security: Prevents a new depositor from immediately capturing harvested yield.

  • validation: None; the raw underlying balance caps the result.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public view.

  • oracle: No oracle dependency.

function totalAssets() public view override returns (uint256 assets);

Returns

NameTypeDescription
assetsuint256Accounted assets available to share holders.

_convertToShares

Converts assets using the series' matched virtual reserves.

Uses the same reserve quote before and after its first accounting synchronization.

Notes:

  • security: Virtual shares preserve conversion precision at small real supply.

  • validation: Checked arithmetic rejects unrepresentable totals.

  • state-changes: None.

  • events: None.

  • errors: Arithmetic overflow.

  • reentrancy: Read-only helper.

  • access: Internal ERC-4626 conversion.

  • oracle: None.

function _convertToShares(uint256 assets, Math.Rounding rounding) internal view override returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256QEURO asset amount.
roundingMath.RoundingDirection of integer rounding.

Returns

NameTypeDescription
sharesuint256Corresponding share amount.

_convertToAssets

Converts shares using the series' matched virtual reserves.

Uses the same reserve as asset-to-share conversion without changing token decimals.

Notes:

  • security: Keeps deposit and exit conversion symmetric.

  • validation: Checked arithmetic rejects unrepresentable totals.

  • state-changes: None.

  • events: None.

  • errors: Arithmetic overflow.

  • reentrancy: Read-only helper.

  • access: Internal ERC-4626 conversion.

  • oracle: None.

function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view override returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Share amount.
roundingMath.RoundingDirection of integer rounding.

Returns

NameTypeDescription
assetsuint256Corresponding QEURO amount.

_virtualAssetReserve

Quotes the backing-bounded virtual asset reserve for this series.

Empty series start at parity. Existing populated series preserve their legacy (assets + 1) / (shares + 1) rate to within one virtual asset base unit. The same bound caps the reserve after losses so total redemption cannot exceed backing.

Notes:

  • security: Scales reserves before the first supply change on an existing series.

  • validation: Checked arithmetic and full-precision multiplication.

  • state-changes: None.

  • events: None.

  • errors: Arithmetic overflow.

  • reentrancy: Read-only helper.

  • access: Internal.

  • oracle: None.

function _virtualAssetReserve() private view returns (uint256 reserve);

Returns

NameTypeDescription
reserveuint256Virtual QEURO reserve in underlying base units.

deposit

Deposits QEURO into the vault and mints stQEURO shares to a receiver.

Wraps the ERC-4626 deposit flow with pause and reentrancy protection.

Notes:

  • security: Protected by pause and nonReentrant guards.

  • validation: Delegates asset, allowance, and receiver checks to ERC-4626/ERC-20 logic.

  • state-changes: Transfers QEURO into the vault and mints new stQEURO shares.

  • events: Emits the standard ERC-4626 Deposit event.

  • errors: Reverts when paused or when ERC-20/ERC-4626 validations fail.

  • reentrancy: Protected by nonReentrant.

  • access: Public.

  • oracle: Not applicable.

function deposit(uint256 assets, address receiver)
    public
    override
    nonReentrant
    whenNotPaused
    returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to deposit.
receiveraddressAddress receiving newly minted stQEURO shares.

Returns

NameTypeDescription
sharesuint256Amount of stQEURO shares minted for receiver.

mint

Mints a target amount of stQEURO shares by supplying the required QEURO assets.

Wraps the ERC-4626 mint flow with pause and reentrancy protection.

Notes:

  • security: Protected by pause and nonReentrant guards.

  • validation: Delegates share, allowance, and receiver checks to ERC-4626/ERC-20 logic.

  • state-changes: Transfers QEURO into the vault and mints stQEURO shares.

  • events: Emits the standard ERC-4626 Deposit event.

  • errors: Reverts when paused or when ERC-20/ERC-4626 validations fail.

  • reentrancy: Protected by nonReentrant.

  • access: Public.

  • oracle: Not applicable.

function mint(uint256 shares, address receiver)
    public
    override
    nonReentrant
    whenNotPaused
    returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to mint.
receiveraddressAddress receiving the minted shares.

Returns

NameTypeDescription
assetsuint256Amount of QEURO assets pulled from the caller.

withdraw

Withdraws a target amount of QEURO assets from the vault.

Wraps the ERC-4626 withdraw flow with pause and reentrancy protection.

Notes:

  • security: Protected by pause and nonReentrant guards.

  • validation: Delegates asset, allowance, and balance checks to ERC-4626/ERC-20 logic.

  • state-changes: Burns stQEURO shares and transfers QEURO assets out of the vault.

  • events: Emits the standard ERC-4626 Withdraw event.

  • errors: Reverts when paused or when ERC-20/ERC-4626 validations fail.

  • reentrancy: Protected by nonReentrant.

  • access: Public.

  • oracle: Not applicable.

function withdraw(uint256 assets, address receiver, address owner)
    public
    override
    nonReentrant
    whenNotPaused
    returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to withdraw.
receiveraddressAddress receiving the withdrawn QEURO.
owneraddressShare owner whose balance and allowance are consumed.

Returns

NameTypeDescription
sharesuint256Amount of stQEURO shares burned to complete the withdrawal.

redeem

Redeems stQEURO shares for their corresponding QEURO assets.

Wraps the ERC-4626 redeem flow with pause and reentrancy protection.

Notes:

  • security: Protected by pause and nonReentrant guards.

  • validation: Delegates share, allowance, and balance checks to ERC-4626/ERC-20 logic.

  • state-changes: Burns stQEURO shares and transfers QEURO assets out of the vault.

  • events: Emits the standard ERC-4626 Withdraw event.

  • errors: Reverts when paused or when ERC-20/ERC-4626 validations fail.

  • reentrancy: Protected by nonReentrant.

  • access: Public.

  • oracle: Not applicable.

function redeem(uint256 shares, address receiver, address owner)
    public
    override
    nonReentrant
    whenNotPaused
    returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to redeem.
receiveraddressAddress receiving the redeemed QEURO.
owneraddressShare owner whose balance and allowance are consumed.

Returns

NameTypeDescription
assetsuint256Amount of QEURO assets transferred to receiver.

_sweepResidualOnEmpty

Clears remaining QEURO after the final share exit.

Returns up to 1e12 wei of rounding dust to the receiver and sends excess to treasury.

Notes:

  • security: Only reachable from nonReentrant exit paths; QEURO has no transfer hooks.

  • validation: No-op unless the share supply is exactly zero.

  • state-changes: Transfers bounded dust to receiver and excess to treasury.

  • events: Emits ResidualSwept when a nonzero residue is transferred.

  • errors: Reverts only if the underlying QEURO transfer fails.

  • reentrancy: Callers hold the nonReentrant guard.

  • access: Internal helper only.

  • oracle: Not applicable.

function _sweepResidualOnEmpty(address receiver) private returns (uint256 residual);

Parameters

NameTypeDescription
receiveraddressAddress that receives the swept residue (same receiver as the exit).

Returns

NameTypeDescription
residualuint256Amount of QEURO swept (0 when shares remain or nothing is left).

setVestingPeriod

Records a new governance-selected vesting period.

Synchronizes already-observed yield before changing the period used for future surplus.

Notes:

  • security: Restricted to governance.

  • validation: Rejects periods outside the bounded safety range.

  • state-changes: Updates the future yield vesting period.

  • events: Emits VestingPeriodUpdated.

  • errors: ConfigValueTooLow or ConfigValueTooHigh.

  • reentrancy: Not applicable.

  • access: Governance role.

  • oracle: No oracle dependency.

function setVestingPeriod(uint256 newPeriod) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newPerioduint256Seconds over which newly observed yield vests (1 day to 30 days).

syncVesting

Materializes currently vested yield and records newly observed surplus.

Permissionless during normal operation; governance may also sync during paused upgrades.

Notes:

  • security: Paused maintenance requires governance authorization.

  • validation: Underlying balance deltas are bounded by the token balance.

  • state-changes: Updates principal, unvested yield, and vesting timestamps.

  • events: Emits YieldVestingSynced.

  • errors: AccessControlUnauthorizedAccount for non-governance callers while paused.

  • reentrancy: Protected by nonReentrant.

  • access: Public when unpaused; GOVERNANCE_ROLE while paused.

  • oracle: No oracle dependency.

function syncVesting() external nonReentrant;

_syncVestingAccounting

function _syncVestingAccounting() private;

_vestedBalanceView

function _vestedBalanceView() private view returns (uint256 vested);

transfer

Transfers stQEURO shares while the vault is active.

Blocks share transfers whenever the vault is paused.

Notes:

  • security: Protected by the pause guard.

  • validation: Delegates recipient, balance, and amount checks to ERC-20 logic.

  • state-changes: Moves stQEURO share balances between accounts.

  • events: Emits the standard ERC-20 Transfer event.

  • errors: Reverts when paused or when ERC-20 validations fail.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function transfer(address to, uint256 value)
    public
    override(ERC20Upgradeable, IERC20)
    whenNotPaused
    returns (bool);

Parameters

NameTypeDescription
toaddressRecipient of the transferred stQEURO shares.
valueuint256Amount of stQEURO shares to transfer.

Returns

NameTypeDescription
<none>boolsuccess True when the transfer succeeds.

transferFrom

Transfers stQEURO shares from another account while the vault is active.

Blocks allowance-based share transfers whenever the vault is paused.

Notes:

  • security: Protected by the pause guard.

  • validation: Delegates allowance, recipient, balance, and amount checks to ERC-20 logic.

  • state-changes: Moves stQEURO share balances between accounts and updates allowance when applicable.

  • events: Emits the standard ERC-20 Transfer event and allowance events when applicable.

  • errors: Reverts when paused or when ERC-20 validations fail.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function transferFrom(address from, address to, uint256 value)
    public
    override(ERC20Upgradeable, IERC20)
    whenNotPaused
    returns (bool);

Parameters

NameTypeDescription
fromaddressAccount whose share balance and allowance are consumed.
toaddressRecipient of the transferred stQEURO shares.
valueuint256Amount of stQEURO shares to transfer.

Returns

NameTypeDescription
<none>boolsuccess True when the transfer succeeds.

updateYieldParameters

Updates the yield fee charged on compounded vault yield.

Governance can set the fee in basis points up to the configured 20% cap.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Validates _yieldFee against the 2000 bps maximum.

  • state-changes: Updates the stored yieldFee.

  • events: Emits YieldParametersUpdated.

  • errors: Reverts on invalid fee values or missing governance role.

  • reentrancy: Not applicable.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Not applicable.

function updateYieldParameters(uint256 _yieldFee) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_yieldFeeuint256New yield fee in basis points.

updateTreasury

Updates the treasury destination used for recovery flows.

Governance can rotate the treasury after standard non-zero and treasury-address validation passes.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Requires a non-zero address that passes treasury validation rules.

  • state-changes: Replaces the stored treasury address.

  • events: Emits TreasuryUpdated.

  • errors: Reverts on invalid treasury addresses or missing governance role.

  • reentrancy: Not applicable.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Not applicable.

function updateTreasury(address _treasury) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address.

pause

Pauses deposits, withdrawals, redemptions, and share transfers.

Emergency role can freeze vault interactions until the pause is lifted.

Notes:

  • security: Restricted to EMERGENCY_ROLE.

  • validation: None.

  • state-changes: Sets the paused state to true.

  • events: Emits the inherited Paused event.

  • errors: Reverts on missing emergency role or if already paused.

  • reentrancy: Not applicable.

  • access: Restricted to EMERGENCY_ROLE.

  • oracle: Not applicable.

function pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpauses deposits, withdrawals, redemptions, and share transfers.

Emergency role can resume normal vault operation after a pause.

Notes:

  • security: Restricted to EMERGENCY_ROLE.

  • validation: None.

  • state-changes: Sets the paused state to false.

  • events: Emits the inherited Unpaused event.

  • errors: Reverts on missing emergency role or if the vault is not paused.

  • reentrancy: Not applicable.

  • access: Restricted to EMERGENCY_ROLE.

  • oracle: Not applicable.

function unpause() external onlyRole(EMERGENCY_ROLE);

emergencyWithdraw

Forces a full emergency redemption of a user's stQEURO position.

Emergency role can burn all of a user's shares and transfer the current redeemable QEURO balance directly to that user.

Notes:

  • security: Restricted to EMERGENCY_ROLE and protected by nonReentrant.

  • validation: Returns early when user holds no shares.

  • state-changes: Burns the user's full share balance and transfers corresponding QEURO assets out of the vault.

  • events: Emits the standard ERC-4626 Withdraw event when shares are burned.

  • errors: Reverts on missing emergency role or failed asset transfer.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to EMERGENCY_ROLE.

  • oracle: Not applicable.

function emergencyWithdraw(address user) external onlyRole(EMERGENCY_ROLE) nonReentrant;

Parameters

NameTypeDescription
useraddressAccount whose full vault position is being unwound.

recoverToken

Recovers non-QEURO ERC-20 tokens mistakenly sent to the vault.

Admin-only recovery route forwards unsupported tokens to the configured treasury and explicitly forbids recovering the underlying asset.

Notes:

  • security: Restricted to DEFAULT_ADMIN_ROLE and blocks recovery of the vault's underlying asset.

  • validation: Requires token to differ from asset().

  • state-changes: Transfers the specified token amount from the vault to the treasury.

  • events: Emits downstream ERC-20 Transfer events from the recovered token.

  • errors: Reverts on invalid token selection, failed transfers, or missing admin role.

  • reentrancy: Not applicable.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: Not applicable.

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressERC-20 token address to recover.
amountuint256Amount of tokens to recover.

recoverETH

Recovers native ETH held by the vault and forwards it to the treasury.

Admin-only recovery route sends the contract's entire ETH balance to the configured treasury.

Notes:

  • security: Restricted to DEFAULT_ADMIN_ROLE.

  • validation: Requires a configured treasury and a positive ETH balance.

  • state-changes: Transfers the full native ETH balance from the vault to the treasury.

  • events: Emits ETHRecovered.

  • errors: Reverts on missing treasury, zero ETH balance, send failure, or missing admin role.

  • reentrancy: Not applicable.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: Not applicable.

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

Events

YieldParametersUpdated

event YieldParametersUpdated(uint256 yieldFee);

TreasuryUpdated

event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury, address indexed caller);

ETHRecovered

event ETHRecovered(address indexed to, uint256 indexed amount);

ResidualSwept

Emitted when the rounding residue left by the final exit is swept to its receiver

event ResidualSwept(address indexed receiver, uint256 amount);

VestingPeriodUpdated

event VestingPeriodUpdated(uint256 oldPeriod, uint256 newPeriod);

YieldVestingSynced

event YieldVestingSynced(uint256 vested, uint256 unvested, uint256 accounted);

Contents

IChainlinkOracle

Git Source

Inherits: IOracle

Title: IChainlinkOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the Quantillon Chainlink-based oracle

Extends IOracle with Chainlink-specific functions This interface is specific to ChainlinkOracle implementation

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the oracle with admin and feed addresses

Sets up the oracle with initial configuration and assigns roles to admin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function initialize(address admin, address _eurUsdPriceFeed, address _usdcUsdPriceFeed, address _treasury) external;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and manager roles
_eurUsdPriceFeedaddressChainlink EUR/USD feed address
_usdcUsdPriceFeedaddressChainlink USDC/USD feed address
_treasuryaddressTreasury address

updatePriceBounds

Updates EUR/USD min and max acceptable prices

Updates the price bounds for EUR/USD validation with security checks

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external;

Parameters

NameTypeDescription
_minPriceuint256New minimum price (18 decimals)
_maxPriceuint256New maximum price (18 decimals)

updateUsdcTolerance

Updates the allowed USDC deviation from $1.00 in basis points

Updates the USDC price tolerance for validation with security checks

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateUsdcTolerance(uint256 newToleranceBps) external;

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance (e.g., 200 = 2%)

updatePriceFeeds

Updates Chainlink feed addresses

Updates the addresses of both Chainlink price feeds with validation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updatePriceFeeds(address _eurUsdFeed, address _usdcUsdFeed) external;

Parameters

NameTypeDescription
_eurUsdFeedaddressNew EUR/USD feed
_usdcUsdFeedaddressNew USDC/USD feed

resetCircuitBreaker

Clears circuit breaker and attempts to resume live prices

Resets the circuit breaker state to allow normal price operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function resetCircuitBreaker() external;

triggerCircuitBreaker

Manually triggers circuit breaker to use fallback prices

Activates circuit breaker to switch to fallback price mode for safety

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function triggerCircuitBreaker() external;

pause

Pauses all oracle operations

Pauses the oracle contract to halt all price operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external;

unpause

Unpauses oracle operations

Resumes oracle operations after being paused

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external;

recoverToken

Recovers ERC20 tokens sent to the oracle contract by mistake

Allows recovery of ERC20 tokens accidentally sent to the oracle contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to transfer

recoverETH

Recovers ETH sent to the oracle contract by mistake

Allows recovery of ETH accidentally sent to the oracle contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

IExecutionPricing

Git Source

Title: IExecutionPricing

Volume-dependent execution pricing and admission for a single vault.

Functions

vault

Vault authorized to consume quoted liquidity.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function vault() external view returns (address);

Returns

NameTypeDescription
<none>addressresult Calculated result in the units described by this operation.

outstanding

Total admitted EUR exposure awaiting acknowledgment, in 18 decimals.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function outstanding() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256result Calculated result in the units described by this operation.

consumeMint

Consume buy liquidity for net USDC input (6 decimals).

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Updates consumed liquidity counters.

  • events: LiquidityConsumed.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Configured vault only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function consumeMint(uint256 netUsdc, uint256 referencePrice)
    external
    returns (uint256 qeuroOut, uint256 backingUsdc);

Parameters

NameTypeDescription
netUsdcuint256Input after protocol fees.
referencePriceuint256Reference USD per EUR in 18 decimals.

Returns

NameTypeDescription
qeuroOutuint256Minted quantity in 18 decimals.
backingUsdcuint256Reference-valued backing in 6 decimals.

consumeRedeem

Consume sell liquidity for QEURO input (18 decimals).

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Updates consumed liquidity counters.

  • events: LiquidityConsumed.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Configured vault only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function consumeRedeem(uint256 qeuroIn, uint256 referencePrice) external returns (uint256 executionUsdc);

Parameters

NameTypeDescription
qeuroInuint256Quantity redeemed.
referencePriceuint256Reference USD per EUR in 18 decimals.

Returns

NameTypeDescription
executionUsdcuint256Payout before protocol fees, in 6 decimals.

IExternalStakingVault

Git Source

Title: IExternalStakingVault

Generic adapter interface for third-party staking/yield vaults.

QuantillonVault interacts with all external yield sources through this surface.

Functions

depositUnderlying

Deposits underlying USDC into the external vault.

Adapter entrypoint used by QuantillonVault for principal deployment.

Notes:

  • security: Implementations should restrict unauthorized callers.

  • validation: Implementations should validate non-zero amount and integration readiness.

  • state-changes: Typically increases adapter-held principal and downstream vault position.

  • events: Implementations should emit deposit/accounting events.

  • errors: Reverts on invalid input or downstream integration failure.

  • reentrancy: Implementations should enforce CEI/nonReentrant where needed.

  • access: Access control is implementation-defined.

  • oracle: No mandatory oracle dependency at interface level.

function depositUnderlying(uint256 usdcAmount) external returns (uint256 sharesReceived);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).

Returns

NameTypeDescription
sharesReceiveduint256Adapter-specific share amount or accounting units received.

withdrawUnderlying

Withdraws underlying USDC from the external vault.

Adapter entrypoint used by QuantillonVault for redemption liquidity.

Notes:

  • security: Implementations should restrict unauthorized callers.

  • validation: Implementations should validate amount and available liquidity.

  • state-changes: Typically decreases adapter-held principal and returns USDC.

  • events: Implementations should emit withdrawal/accounting events.

  • errors: Reverts on invalid input or downstream integration failure.

  • reentrancy: Implementations should enforce CEI/nonReentrant where needed.

  • access: Access control is implementation-defined.

  • oracle: No mandatory oracle dependency at interface level.

function withdrawUnderlying(uint256 usdcAmount) external returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to withdraw (6 decimals).

Returns

NameTypeDescription
usdcWithdrawnuint256Actual USDC withdrawn.

harvestYieldToVault

Harvests accrued yield and transfers it as USDC to the caller (the vault).

Routes the realized yield back to msg.sender (the vault) so the caller can apply the protocol's own distribution policy (hedger/user/treasury split). Realizes only the amount above tracked principal; principal is left untouched.

Notes:

  • security: Implementations should restrict unauthorized callers.

  • validation: Implementations should validate source state before harvesting.

  • state-changes: Realizes yield and transfers USDC out to the caller; principal unchanged.

  • events: Implementations should emit harvest/transfer events.

  • errors: Reverts on invalid state or downstream integration failure.

  • reentrancy: Implementations should enforce CEI/nonReentrant where needed.

  • access: Access control is implementation-defined.

  • oracle: No mandatory oracle dependency at interface level.

function harvestYieldToVault() external returns (uint256 realizedYield);

Returns

NameTypeDescription
realizedYielduint256Yield realized and transferred to the caller in USDC (6 decimals).

totalUnderlying

Returns total underlying value currently controlled by the adapter.

View helper for exposure accounting (principal + accrued yield).

Notes:

  • security: Read-only helper.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Implementations may revert on unavailable downstream reads.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: Oracle use is implementation-defined.

function totalUnderlying() external view returns (uint256 underlyingBalance);

Returns

NameTypeDescription
underlyingBalanceuint256Underlying USDC-equivalent balance (6 decimals).

IHedgerPool

Git Source

Functions

executeWithReference

Execute an allowed hedger operation with a signed valuation report.

Submits the reference and delegates only a permitted selector, preserving the caller.

Notes:

  • security: Grants no additional caller permissions.

  • validation: Validates the report, selector and underlying operation.

  • state-changes: Reference and operation state change atomically.

  • events: ReferenceAccepted and underlying operation events.

  • errors: Reverts on invalid reports, selectors or operation guards.

  • reentrancy: Retains the underlying operation's reentrancy guard.

  • access: Underlying hedger operation permissions.

  • oracle: Governed signed reference source.

function executeWithReference(bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesEncoded permitted HedgerPool operation.
authorizationbytesEncoded reference report and signature.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the underlying operation.

removeMarginWithReference

Withdraw caller-owned USDC margin with an atomic reference refresh.

Explicit parameters allow Roles to constrain position and amount.

Notes:

  • security: Preserves ownership, collateral and pause checks.

  • validation: Validates the reference and withdrawal limits.

  • state-changes: Reference and margin accounting revert together on failure.

  • events: ReferenceAccepted and margin withdrawal events.

  • errors: Propagates reference and withdrawal errors.

  • reentrancy: Retains removeMargin's reentrancy guard.

  • access: Position owner.

  • oracle: Governed signed reference source.

function removeMarginWithReference(uint256 positionId, uint256 amount, bytes calldata authorization)
    external
    returns (bytes memory);

Parameters

NameTypeDescription
positionIduint256Position owned by the original caller.
amountuint256USDC margin to withdraw, in six decimals.
authorizationbytesEncoded reference report and signature.

Returns

NameTypeDescription
<none>bytesABI-encoded withdrawal result, empty on success.

manageHedgerMigration

Proposes (0), accepts (1), executes (2), or cancels (3) a live ownership transfer.

Owner proposes, recipient accepts, governance executes while paused; any of these may cancel.

Notes:

  • security: Requires all three authorities; proposals expire within seven days.

  • validation: Requires active cost-basis accounting and a recipient contract without pool state.

  • state-changes: Updates proposal state or moves ownership and pool reward claims.

  • events: HedgerMigrationProposed, HedgerMigrationAccepted, HedgerMigrationExecuted, HedgerMigrationCancelled, SingleHedgerRotationApplied.

  • errors: Reverts on invalid authority, proposal, expiry, pause or recipient state.

  • reentrancy: Protected by the pool guard; no token transfers.

  • access: Current hedger, receiving contract or governance according to action.

  • oracle: No oracle calls; position economics remain intact.

function manageHedgerMigration(HedgerMigrationRequest calldata request) external;

Parameters

NameTypeDescription
requestHedgerMigrationRequestAction and exact proposal binding; proposing uses a zero proposal ID.

hedgerMigration

Returns the current transfer proposal, or zeros if none exists.

Dedicated proposal namespace does not change existing position storage.

Notes:

  • security: Read only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: No external state changes.

  • access: Public.

  • oracle: No oracle dependencies.

function hedgerMigration() external view returns (HedgerMigrationProposal memory proposal);

Returns

NameTypeDescription
proposalHedgerMigrationProposalCurrent ownership transfer proposal.

initializeCostBasisAccounting

Activates remaining-cost accounting on a paused, fully settled proxy.

Fresh deployments activate during initialization; an upgraded proxy activates once.

Notes:

  • security: Restricted to governance with no active position or outstanding exposure.

  • validation: Requires a paused pool, zero counters and QEURO supply at most dust.

  • state-changes: Activates remaining-cost accounting.

  • events: Emits Initialized.

  • errors: Reverts when caller, pause, settlement or initialization checks fail.

  • reentrancy: No state-changing external calls.

  • access: GOVERNANCE_ROLE.

  • oracle: No oracle dependencies.

function initializeCostBasisAccounting() external;

costBasisAccountingInitialized

Reports whether remaining-cost accounting is active.

False on an upgraded proxy until settlement and activation are complete.

Notes:

  • security: Read-only getter.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: No external calls.

  • access: Public.

  • oracle: No oracle dependencies.

function costBasisAccountingInitialized() external view returns (bool initialized);

Returns

NameTypeDescription
initializedboolWhether the accounting model has been activated.

initialize

Initializes the HedgerPool contract.

Sets up core references, roles and timelock required for hedger operations.

Notes:

  • security: Validates non‑zero addresses and configures roles.

  • validation: Reverts on zero addresses or inconsistent configuration.

  • state-changes: Initializes storage, roles and external references.

  • events: Emits implementation‑specific initialization events.

  • errors: Reverts with protocol‑specific errors on invalid configuration.

  • reentrancy: Protected by initializer modifier in implementation.

  • access: External initializer; callable only once by deployer/timelock.

  • oracle: No live oracle reads; only stores oracle address.

function initialize(
    address admin,
    address _usdc,
    address _oracle,
    address _yieldShift,
    address _timelock,
    address _treasury,
    address _vault
) external;

Parameters

NameTypeDescription
adminaddressAddress receiving admin and governance roles.
_usdcaddressUSDC token address used for margin and PnL settlement.
_oracleaddressOracle contract used to obtain EUR/USD prices.
_yieldShiftaddressYieldShift contract used for hedger reward accounting.
_timelockaddressTimelock contract used for secure upgrades.
_treasuryaddressTreasury address receiving protocol fees / recoveries.
_vaultaddressQuantillonVault address holding unified USDC liquidity.

enterHedgePosition

Opens a new hedge position using USDC margin.

Locks usdcAmount as margin and creates a leveraged EUR short/long exposure.

Notes:

  • security: Validates margin ratios, leverage bounds and single‑hedger constraints.

  • validation: Reverts on zero amount, invalid leverage or insufficient balance.

  • state-changes: Updates margin, exposure and internal position bookkeeping.

  • events: Emits HedgePositionOpened.

  • errors: Reverts with protocol‑specific risk/validation errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Callable by authorized hedger addresses.

  • oracle: Uses oracle price for margin and exposure checks.

function enterHedgePosition(uint256 usdcAmount, uint256 leverage) external returns (uint256 positionId);

Parameters

NameTypeDescription
usdcAmountuint256Margin amount in USDC (6 decimals) to lock.
leverageuint256Leverage multiplier applied to margin.

Returns

NameTypeDescription
positionIduint256Identifier of the newly created hedge position.

exitHedgePosition

Closes an existing hedge position.

Unwinds exposure, realizes PnL and releases remaining margin to the hedger.

Notes:

  • security: Enforces ownership and minimum hold time before closure.

  • validation: Reverts if position is inactive or caller is not the hedger.

  • state-changes: Updates margin totals, exposure and realized PnL fields.

  • events: Emits HedgePositionClosed.

  • errors: Reverts with protocol‑specific position or risk errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Callable by the owning hedger (and possibly governance/emergency).

  • oracle: Uses latest oracle price to compute final PnL.

function exitHedgePosition(uint256 positionId) external returns (int256 pnl);

Parameters

NameTypeDescription
positionIduint256Identifier of the position to close.

Returns

NameTypeDescription
pnlint256Signed realized PnL in USDC terms.

addMargin

Adds additional margin to an existing position.

Increases margin and recomputes position metrics while keeping exposure rules intact.

Notes:

  • security: Enforces ownership and validates that position is active.

  • validation: Reverts on zero amount or inactive position.

  • state-changes: Increases per‑position and total margin.

  • events: Emits MarginUpdated.

  • errors: Reverts with protocol‑specific margin/validation errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Callable by the owning hedger.

  • oracle: May use oracle indirectly in risk checks.

function addMargin(uint256 positionId, uint256 amount) external;

Parameters

NameTypeDescription
positionIduint256Identifier of the position to top‑up.
amountuint256USDC amount to add as extra margin.

removeMargin

Removes margin from an existing position.

Decreases margin subject to min margin ratio and min margin amount constraints.

Notes:

  • security: Prevents margin removal that would violate risk constraints.

  • validation: Reverts on zero amount, inactive position or under‑margining.

  • state-changes: Decreases per‑position and total margin.

  • events: Emits MarginUpdated.

  • errors: Reverts with protocol‑specific risk/validation errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Callable by the owning hedger.

  • oracle: Uses oracle price via risk libraries.

function removeMargin(uint256 positionId, uint256 amount) external;

Parameters

NameTypeDescription
positionIduint256Identifier of the position to adjust.
amountuint256USDC amount of margin to remove.

recordUserMint

Records a user mint event for hedger accounting.

Called by QuantillonVault when users mint QEURO so hedger exposure can be tracked.

Notes:

  • security: Callable only by the vault; validates caller and parameters.

  • validation: Reverts on zero amounts or unauthorized caller.

  • state-changes: Updates aggregated exposure and PnL tracking for hedgers.

  • events: Emits internal accounting events in implementation.

  • errors: Reverts with protocol‑specific accounting errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to QuantillonVault.

  • oracle: Expects fillPrice to be derived from a validated oracle path.

function recordUserMint(uint256 usdcAmount, uint256 fillPrice, uint256 qeuroAmount) external;

Parameters

NameTypeDescription
usdcAmountuint256USDC amount entering the system from the mint.
fillPriceuint256Oracle mint price used for the operation.
qeuroAmountuint256QEURO minted to the user.

recordUserRedeem

Records a user redeem event for hedger accounting.

Called by QuantillonVault when users redeem QEURO back to USDC.

Notes:

  • security: Callable only by the vault; validates caller and parameters.

  • validation: Reverts on zero amounts or unauthorized caller.

  • state-changes: Updates aggregated exposure and realized PnL for hedgers.

  • events: Emits internal accounting events in implementation.

  • errors: Reverts with protocol‑specific accounting errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to QuantillonVault.

  • oracle: Expects redeemPrice to be derived from a validated oracle path.

function recordUserRedeem(uint256 usdcAmount, uint256 redeemPrice, uint256 qeuroAmount) external;

Parameters

NameTypeDescription
usdcAmountuint256USDC paid out to the user.
redeemPriceuint256Oracle price used for the redemption.
qeuroAmountuint256QEURO burned from the user.

recordLiquidationRedeem

Records a pro‑rata liquidation redeem event.

Called when QEURO redemptions happen in liquidation mode so hedger metrics can be aligned with total supply.

Notes:

  • security: Callable only by authorized vault component.

  • validation: Reverts on inconsistent supply or zero amounts.

  • state-changes: Updates hedger exposure and PnL tracking.

  • events: Emits internal accounting events in implementation.

  • errors: Reverts with protocol‑specific accounting errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to vault modules.

  • oracle: Indirectly depends on vault’s oracle‑validated paths.

function recordLiquidationRedeem(uint256 qeuroAmount, uint256 totalQeuroSupply) external;

Parameters

NameTypeDescription
qeuroAmountuint256QEURO amount redeemed under liquidation mode.
totalQeuroSupplyuint256Total QEURO supply at the time of redemption.

claimHedgingRewards

Claims accumulated hedging rewards for the caller.

Aggregates interest differential and yield‑shift rewards into a single payout.

Notes:

  • security: Enforces that caller is an eligible hedger.

  • validation: Reverts if there is no claimable amount.

  • state-changes: Decreases internal reward pools and updates last‑claim markers.

  • events: None (the HedgingRewardsClaimed event was removed in v1.0.1).

  • errors: Reverts with protocol‑specific reward errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Public – callable by hedgers.

  • oracle: No direct oracle dependency; uses already‑accounted rewards.

function claimHedgingRewards()
    external
    returns (uint256 interestDifferential, uint256 yieldShiftRewards, uint256 totalRewards);

Returns

NameTypeDescription
interestDifferentialuint256Portion of rewards from interest‑rate differential.
yieldShiftRewardsuint256Portion of rewards from YieldShift allocations.
totalRewardsuint256Total rewards transferred to the caller.

withdrawPendingRewards

Withdraws pending rewards to a specified recipient.

Allows an operator (or the hedger) to withdraw accrued rewards to recipient.

Notes:

  • security: Enforces authorization for withdrawing on behalf of hedgers.

  • validation: Reverts if recipient is zero or there are no pending rewards.

  • state-changes: Decreases pending reward balances and transfers USDC.

  • events: Emits reward‑withdrawal events in implementation.

  • errors: Reverts with protocol‑specific reward or access errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to authorized roles or hedgers as defined by implementation.

  • oracle: No direct oracle dependency.

function withdrawPendingRewards(address recipient) external;

Parameters

NameTypeDescription
recipientaddressAddress receiving the pending rewards.

getTotalEffectiveHedgerCollateral

Returns the total effective hedger collateral at a given price.

Aggregates per‑position collateral after applying current price and haircuts.

Notes:

  • security: View function; caller must source a sane currentPrice.

  • validation: Returns 0 if no active positions or if price is invalid.

  • state-changes: None – view function.

  • events: None.

  • errors: None – callers handle interpretation.

  • reentrancy: Not applicable – view function.

  • access: Public – used by vault and monitoring tools.

  • oracle: Expects currentPrice to come from a validated oracle.

function getTotalEffectiveHedgerCollateral(uint256 currentPrice)
    external
    view
    returns (uint256 totalEffectiveCollateral);

Parameters

NameTypeDescription
currentPriceuint256Current EUR/USD oracle price used for collateral computation.

Returns

NameTypeDescription
totalEffectiveCollateraluint256Effective hedger collateral in USDC terms.

hasActiveHedger

Returns whether there is at least one active hedger position.

Used by the vault to check that the protocol is hedged.

Notes:

  • security: View function; no access restriction.

  • validation: None.

  • state-changes: None – view function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public – anyone can inspect hedger activity.

  • oracle: No direct oracle dependency.

function hasActiveHedger() external view returns (bool hasActive);

Returns

NameTypeDescription
hasActiveboolTrue if at least one hedger has an active position.

configureRiskAndFees

Configures core hedger risk parameters and fee schedule.

Updates leverage, margin, interest and fee parameters in a single call.

Notes:

  • security: Restricted to governance; misconfiguration can break risk model.

  • validation: Implementation validates each field is within allowed bounds.

  • state-changes: Updates internal risk configuration used for all positions.

  • events: Emits configuration‑update events.

  • errors: Reverts with protocol‑specific config errors.

  • reentrancy: Not applicable – configuration only.

  • access: Restricted to governance roles.

  • oracle: No direct oracle dependency.

function configureRiskAndFees(HedgerRiskConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgHedgerRiskConfigStruct containing all risk and fee configuration fields.

configureDependencies

Configures external dependencies used by HedgerPool.

Wires treasury, vault, oracle, YieldShift and FeeCollector references.

Notes:

  • security: Restricted to governance; validates non‑zero and compatible addresses.

  • validation: Reverts on zero addresses or invalid dependencies.

  • state-changes: Updates contract references used for hedger operations.

  • events: Emits dependency‑update events.

  • errors: Reverts with protocol‑specific config errors.

  • reentrancy: Not applicable – configuration only.

  • access: Restricted to governance roles.

  • oracle: No direct oracle dependency.

function configureDependencies(HedgerDependencyConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgHedgerDependencyConfigStruct specifying dependency addresses.

emergencyClosePosition

Emergency closure of a specific hedger position.

Allows governance/emergency role to forcibly close a position in extreme cases.

Notes:

  • security: Restricted to emergency/governance roles; bypasses normal hedger flow.

  • validation: Reverts if position is already inactive or hedger mismatch.

  • state-changes: Realizes PnL and updates margin/exposure like a normal close.

  • events: Emits HedgePositionClosed with emergency context.

  • errors: Reverts with protocol‑specific position errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to emergency/governance roles.

  • oracle: Uses oracle price for PnL computation.

function emergencyClosePosition(address hedger, uint256 positionId) external;

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger whose position is being closed.
positionIduint256Identifier of the position to close.

pause

Pauses HedgerPool operations.

Emergency function that halts user‑facing state‑changing methods.

Notes:

  • security: Restricted to EMERGENCY_ROLE in implementation.

  • validation: None.

  • state-changes: Sets paused state to true.

  • events: Emits Paused from OpenZeppelin.

  • errors: None – pause is best‑effort.

  • reentrancy: Not applicable – no external calls.

  • access: Emergency‑only.

  • oracle: No oracle dependency.

function pause() external;

unpause

Unpauses HedgerPool operations.

Resumes normal operation after an emergency pause.

Notes:

  • security: Restricted to EMERGENCY_ROLE in implementation.

  • validation: None.

  • state-changes: Sets paused state to false.

  • events: Emits Unpaused from OpenZeppelin.

  • errors: None.

  • reentrancy: Not applicable – no external calls.

  • access: Emergency‑only.

  • oracle: No oracle dependency.

function unpause() external;

recover

Recovers arbitrary ERC20 tokens from the contract.

Intended only for governance to recover tokens that are not part of normal flows.

Notes:

  • security: Restricted to governance/treasury roles; never used for user margin.

  • validation: Reverts on zero token, zero amount or insufficient balance.

  • state-changes: Transfers tokens from HedgerPool to treasury or designated address.

  • events: Emits recovery events in implementation.

  • errors: Reverts with protocol‑specific recovery errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to governance/admin.

  • oracle: No oracle dependency.

function recover(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address to recover.
amountuint256Amount of tokens to send to treasury.

setSingleHedger

Sets the designated single hedger address.

Configures an address that is allowed to act as the sole hedger when single‑hedger mode is enabled.

Notes:

  • security: Restricted to governance; validates hedger is non‑zero.

  • validation: May enforce that previous rotation has completed.

  • state-changes: Updates single‑hedger configuration state.

  • events: Emits SingleHedgerRotationApplied.

  • errors: Reverts on invalid hedger address.

  • reentrancy: Not applicable – configuration only.

  • access: Restricted to governance roles.

  • oracle: No oracle dependency.

function setSingleHedger(address hedger) external;

Parameters

NameTypeDescription
hedgeraddressAddress proposed as single hedger.

fundRewardReserve

Funds the reward reserve used to pay hedger rewards.

Transfers USDC from caller into the reward reserve accounting balance.

Notes:

  • security: Callable by treasury/governance; validates positive amount.

  • validation: Reverts on zero amount or insufficient allowance.

  • state-changes: Increases internal reward reserve and vault balances.

  • events: Emits RewardReserveFunded.

  • errors: Reverts with protocol‑specific funding errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to treasury/governance roles.

  • oracle: No oracle dependency.

function fundRewardReserve(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256Amount of USDC to add to the reserve.

usdc

Returns the USDC token used for margin and settlement.

Exposes the ERC20 collateral token that backs hedger margin and PnL.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function usdc() external view returns (IERC20 usdcToken);

Returns

NameTypeDescription
usdcTokenIERC20IERC20 instance of the USDC token.

oracle

Returns the oracle contract address used for pricing.

This oracle is used by the implementation to value exposure and margin.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Exposes the price‑feed dependency.

function oracle() external view returns (address oracleAddress);

Returns

NameTypeDescription
oracleAddressaddressAddress of the oracle.

yieldShift

Returns the YieldShift contract address.

YieldShift is responsible for computing and distributing protocol yield.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function yieldShift() external view returns (address yieldShiftAddress);

Returns

NameTypeDescription
yieldShiftAddressaddressAddress of the YieldShift contract.

vault

Returns the QuantillonVault contract address.

Vault holds unified USDC liquidity shared between users and hedgers.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function vault() external view returns (address vaultAddress);

Returns

NameTypeDescription
vaultAddressaddressAddress of the vault contract.

treasury

Returns the treasury address used for fee flows.

Treasury receives protocol fees and recovered funds from HedgerPool.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function treasury() external view returns (address treasuryAddress);

Returns

NameTypeDescription
treasuryAddressaddressTreasury address.

coreParams

Returns packed core hedger parameters.

Exposes key risk and fee parameters as a compact tuple.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for UI and risk monitoring.

  • oracle: No oracle dependency.

function coreParams()
    external
    view
    returns (
        uint64 minMarginRatio,
        uint16 maxLeverage,
        uint16 entryFee,
        uint16 exitFee,
        uint16 marginFee,
        uint16 eurInterestRate,
        uint16 usdInterestRate,
        uint8 reserved
    );

Returns

NameTypeDescription
minMarginRatiouint64Minimum margin ratio (bps).
maxLeverageuint16Maximum allowed leverage (1e2 or similar scaling).
entryFeeuint16Entry fee (bps).
exitFeeuint16Exit fee (bps).
marginFeeuint16Ongoing margin fee (bps).
eurInterestRateuint16EUR interest rate (bps).
usdInterestRateuint16USD interest rate (bps).
reserveduint8Reserved field for future use.

totalMargin

Returns the total margin locked across all hedger positions.

Sums the margin field of every active position, in USDC units.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function totalMargin() external view returns (uint256 margin);

Returns

NameTypeDescription
marginuint256Total margin in USDC terms.

totalExposure

Returns the total notional exposure of all hedger positions.

Aggregates leveraged notional position sizes across all active hedgers.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function totalExposure() external view returns (uint256 exposure);

Returns

NameTypeDescription
exposureuint256Total position size in notional units.

totalFilledExposure

Returns the total filled exposure across all positions.

Tracks how much of the theoretical exposure is actually filled in the market.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function totalFilledExposure() external view returns (uint256 filledExposure);

Returns

NameTypeDescription
filledExposureuint256Total filled exposure.

singleHedger

Returns the currently active single hedger address.

When single‑hedger mode is enabled, only this address may open positions.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function singleHedger() external view returns (address hedgerAddress);

Returns

NameTypeDescription
hedgerAddressaddressSingle hedger address, or zero if not configured.

minPositionHoldBlocks

Returns the minimum number of blocks a position must be held.

Used to prevent instant in‑and‑out hedger positions around price updates.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function minPositionHoldBlocks() external view returns (uint256 minBlocks);

Returns

NameTypeDescription
minBlocksuint256Minimum position hold in blocks.

minMarginAmount

Returns the minimum allowed margin amount for a position.

Positions with margin below this threshold are not allowed to open.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function minMarginAmount() external view returns (uint256 minMargin);

Returns

NameTypeDescription
minMarginuint256Minimum margin in USDC terms.

pendingRewardWithdrawals

Returns pending reward withdrawals for a specific hedger.

Shows how much claimable USDC yield is currently assigned to hedger.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – hedgers and UIs can inspect claimable rewards.

  • oracle: No oracle dependency.

function pendingRewardWithdrawals(address hedger) external view returns (uint256 amount);

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger.

Returns

NameTypeDescription
amountuint256Pending reward amount in USDC.

feeCollector

Returns the FeeCollector contract address.

FeeCollector aggregates protocol fees before they are routed to treasury or rewards.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function feeCollector() external view returns (address feeCollectorAddress);

Returns

NameTypeDescription
feeCollectorAddressaddressAddress of the fee collector.

rewardFeeSplit

Returns the current reward fee split between treasury and hedgers.

Implementations use this split to decide how collected fees are allocated.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function rewardFeeSplit() external view returns (uint256 split);

Returns

NameTypeDescription
splituint256Reward fee split as a fraction (bps or 1e18‑scaled per implementation).

MAX_REWARD_FEE_SPLIT

Returns the maximum allowed reward fee split.

Governance cannot configure rewardFeeSplit above this constant.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function MAX_REWARD_FEE_SPLIT() external view returns (uint256 maxSplit);

Returns

NameTypeDescription
maxSplituint256Maximum allowed split constant.

hedgerLastRewardBlock

Returns the last block number at which a hedger claimed rewards.

Useful for enforcing minimum intervals between reward claims.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function hedgerLastRewardBlock(address hedger) external view returns (uint256 lastRewardBlock);

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger.

Returns

NameTypeDescription
lastRewardBlockuint256Block number of the last reward claim.

positions

Returns full position data for a given position id.

Provides a denormalized snapshot of all key risk metrics for off‑chain monitoring.

Notes:

  • security: View‑only; no access restriction.

  • validation: Returns zeroed values for nonexistent positions.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for analytics and monitoring.

  • oracle: No oracle dependency.

function positions(uint256 positionId)
    external
    view
    returns (
        address hedger,
        uint96 positionSize,
        uint96 filledVolume,
        uint96 margin,
        uint96 entryPrice,
        uint32 entryTime,
        uint32 lastUpdateTime,
        int128 unrealizedPnL,
        int128 realizedPnL,
        uint16 leverage,
        bool isActive,
        uint128 qeuroBacked,
        uint64 openBlock
    );

Parameters

NameTypeDescription
positionIduint256Identifier of the position.

Returns

NameTypeDescription
hedgeraddressHedger address owning the position.
positionSizeuint96Current notional position size.
filledVolumeuint96Filled hedge volume.
marginuint96Current margin allocated to the position.
entryPriceuint96Price at which the position was opened.
entryTimeuint32Timestamp of position opening.
lastUpdateTimeuint32Timestamp of last position update.
unrealizedPnLint128Current unrealized PnL (signed).
realizedPnLint128Realized PnL accumulated so far (signed).
leverageuint16Position leverage.
isActiveboolWhether the position is currently active.
qeuroBackeduint128Amount of QEURO backed by this position.
openBlockuint64Block number at which the position was opened.

Events

HedgePositionOpened

event HedgePositionOpened(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

HedgePositionClosed

event HedgePositionClosed(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

MarginUpdated

event MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData);

RewardReserveFunded

event RewardReserveFunded(address indexed funder, uint256 amount);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

Structs

HedgerMigrationRequest

struct HedgerMigrationRequest {
    uint8 action;
    address newHedger;
    uint64 expiresAt;
    bytes32 proposalId;
}

HedgerMigrationProposal

struct HedgerMigrationProposal {
    bytes32 id;
    address previousHedger;
    address newHedger;
    uint64 expiresAt;
    uint64 openBlock;
    bool accepted;
}

HedgerRiskConfig

struct HedgerRiskConfig {
    uint256 minMarginRatio;
    uint256 maxLeverage;
    uint256 minPositionHoldBlocks;
    uint256 minMarginAmount;
    uint256 eurInterestRate;
    uint256 usdInterestRate;
    uint256 entryFee;
    uint256 exitFee;
    uint256 marginFee;
    uint256 rewardFeeSplit;
}

HedgerDependencyConfig

struct HedgerDependencyConfig {
    address treasury;
    address vault;
    address oracle;
    address yieldShift;
    address feeCollector;
}

IHyperliquidOracle

Git Source

Inherits: IOracle

Title: IHyperliquidOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the Quantillon Hyperliquid EUR/USD oracle adapter

Extends IOracle with the management functions the OracleRouter delegates to the active oracle (updatePriceBounds / updateUsdcTolerance / resetCircuitBreaker / triggerCircuitBreaker) plus adapter-specific configuration. The EUR/USD price is the Hyperliquid xyz:EUR perp mid published on-chain by the off-chain Slippage Monitor into SlippageStorage; USDC/USD validation is delegated to the existing ChainlinkOracle. The OracleRouter stores the active oracle as IStorkOracle and casts it unchecked, so an implementation only needs to expose the IOracle reads plus the four delegated management selectors above to slot into the Stork position via updateOracleAddresses + switchOracle.

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the adapter with its price sources and treasury

Callable once via the proxy. Grants admin/manager/emergency/upgrader roles to admin.

Notes:

  • security: Validates all addresses are non-zero and grants roles to admin

  • validation: Validates admin/_slippageStorage/_usdcSource/_treasury != address(0)

  • state-changes: Initializes sources, roles, default bounds, staleness and tolerance

  • events: Emits PriceUpdated if an initial mid is available

  • errors: Reverts if any address is zero

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during proxy deployment

  • oracle: Reads the initial mid from SlippageStorage if present

function initialize(
    address admin,
    address _slippageStorage,
    uint8 _sourceId,
    address _usdcSource,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and management roles
_slippageStorageaddressSlippageStorage contract that holds the published Hyperliquid mid
_sourceIduint8Slippage source id to read (SOURCE_HYPERLIQUID = 1)
_usdcSourceaddressOracle providing USDC/USD (the existing ChainlinkOracle)
_treasuryaddressTreasury address for ETH/token recovery

updatePriceBounds

Updates EUR/USD min and max acceptable prices (18 decimals)

The bounds gate the validation path; both must be nonzero with min below max.

Notes:

  • security: Misconfigured bounds can force fallback pricing

  • validation: Reverts unless 0 < _minPrice < _maxPrice

  • events: Emits a bounds-updated event in the implementation

  • errors: Reverts on invalid bounds

  • reentrancy: No external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • state-changes: Updates minEurUsdPrice / maxEurUsdPrice

  • oracle: Affects EUR/USD validation only

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external;

Parameters

NameTypeDescription
_minPriceuint256Minimum accepted EUR/USD price (18 decimals)
_maxPriceuint256Maximum accepted EUR/USD price (18 decimals)

updateUsdcTolerance

Updates the reported USDC tolerance in basis points

Reported via getOracleConfig only — USDC validation itself is delegated to the USDC source.

Notes:

  • security: Reporting-only; does not change validation behavior

  • validation: Bounded by the implementation's tolerance cap

  • events: Emits a tolerance-updated event in the implementation

  • errors: Reverts when above the cap

  • reentrancy: No external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • state-changes: Updates the stored tolerance

  • oracle: No effect on price reads

function updateUsdcTolerance(uint256 newToleranceBps) external;

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance in basis points

resetCircuitBreaker

Clears the circuit breaker and attempts to re-seed the price

Re-seeds the deviation baseline from the current published mid when it is valid.

Notes:

  • security: Re-enables live pricing after an incident review

  • validation: None beyond role check

  • events: Emits a breaker-reset event in the implementation

  • errors: None

  • reentrancy: Reads SlippageStorage

  • access: Restricted to EMERGENCY_ROLE

  • state-changes: Clears circuitBreakerTriggered; may update the baseline

  • oracle: Reads the published mid to re-seed

function resetCircuitBreaker() external;

triggerCircuitBreaker

Manually triggers the circuit breaker (use last valid price)

Forces reads onto the last valid price with isValid=false until reset.

Notes:

  • security: Emergency lever to freeze pricing on a bad feed

  • validation: None beyond role check

  • events: Emits a breaker-triggered event in the implementation

  • errors: None

  • reentrancy: No external calls

  • access: Restricted to EMERGENCY_ROLE

  • state-changes: Sets circuitBreakerTriggered

  • oracle: Live reads are suspended until reset

function triggerCircuitBreaker() external;

setMaxPriceStaleness

Updates the maximum accepted staleness (seconds) of the published mid

Gates the timestamp validation; capped by the implementation's hard maximum.

Notes:

  • security: Too-large windows accept outdated prices

  • validation: Reverts above the hard cap

  • events: Emits a staleness-updated event in the implementation

  • errors: Reverts on zero or above-cap values

  • reentrancy: No external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • state-changes: Updates the staleness window

  • oracle: Affects freshness validation of the published mid

function setMaxPriceStaleness(uint256 newMaxStaleness) external;

Parameters

NameTypeDescription
newMaxStalenessuint256New staleness window in seconds

updateSlippageSource

Updates the SlippageStorage source contract and source id

Points the adapter at a new SlippageStorage deployment and/or source id.

Notes:

  • security: The new source becomes the EUR/USD price authority

  • validation: Reverts on zero address

  • events: Emits a source-updated event in the implementation

  • errors: Reverts on zero address

  • reentrancy: No external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • state-changes: Updates slippageStorage and sourceId

  • oracle: Changes where the EUR/USD mid is read from

function updateSlippageSource(address _slippageStorage, uint8 _sourceId) external;

Parameters

NameTypeDescription
_slippageStorageaddressNew SlippageStorage contract address
_sourceIduint8New slippage source id to read

updateUsdcSource

Updates the USDC/USD source oracle (ChainlinkOracle)

Swaps the delegated USDC/USD oracle.

Notes:

  • security: The new source becomes the USDC/USD validation authority

  • validation: Reverts on zero address

  • events: Emits a source-updated event in the implementation

  • errors: Reverts on zero address

  • reentrancy: No external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • state-changes: Updates usdcSource

  • oracle: Changes the delegated USDC/USD feed

function updateUsdcSource(address _usdcSource) external;

Parameters

NameTypeDescription
_usdcSourceaddressNew USDC/USD oracle address

updateTreasury

Updates the treasury address

The treasury receives recovered tokens/ETH from the recovery functions.

Notes:

  • security: Recovery destination changes with this address

  • validation: Reverts on zero address

  • events: Emits TreasuryUpdated

  • errors: Reverts on zero address

  • reentrancy: No external calls

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • state-changes: Updates treasury

  • oracle: No oracle dependency

function updateTreasury(address _treasury) external;

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

pause

Pauses oracle reads

While paused, price reads return the last valid price with isValid=false.

Notes:

  • security: Emergency stop for live pricing

  • validation: None beyond role check

  • events: Emits Paused

  • errors: Reverts when already paused

  • reentrancy: No external calls

  • access: Restricted to EMERGENCY_ROLE

  • state-changes: Sets the paused flag

  • oracle: Live reads suspended

function pause() external;

unpause

Unpauses oracle reads

Re-enables live price reads.

Notes:

  • security: Restores live pricing

  • validation: None beyond role check

  • events: Emits Unpaused

  • errors: Reverts when not paused

  • reentrancy: No external calls

  • access: Restricted to EMERGENCY_ROLE

  • state-changes: Clears the paused flag

  • oracle: Live reads resume

function unpause() external;

recoverToken

Recovers ERC20 tokens to treasury

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Funds can only reach the configured treasury

  • validation: Validated by TreasuryRecoveryLibrary

  • events: Emits a recovery event in the implementation

  • errors: Reverts on invalid token or amount

  • reentrancy: Token transfer to the treasury

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • state-changes: Transfers the token balance

  • oracle: No oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken contract address to recover
amountuint256Amount of tokens to recover

recoverETH

Recovers ETH to treasury

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Funds can only reach the configured treasury

  • validation: Validated by TreasuryRecoveryLibrary

  • events: Emits a recovery event in the implementation

  • errors: Reverts when there is no ETH balance

  • reentrancy: ETH send to the treasury

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • state-changes: Transfers the ETH balance

  • oracle: No oracle dependency

function recoverETH() external;

IMarketOracleAdmin

Git Source

Title: IMarketOracleAdmin

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Minimal admin surface shared by every oracle that can occupy the router's MARKET slot (slot 1)

The OracleRouter delegates manager operations to the active oracle. Slot-1 implementations (StorkOracle historically, HyperliquidEurUsdOracle currently) all expose these four selectors with identical signatures; this interface lets the router address them without coupling to a concrete implementation name.

Note: security-contact: team@quantillon.money

Functions

updatePriceBounds

Updates EUR/USD min and max acceptable prices

Implementation-defined validation; caller is the router (ORACLE_MANAGER_ROLE)

Notes:

  • security: Restricted by the implementing oracle's access control

  • validation: Via implementing oracle

  • state-changes: Oracle price bounds

  • events: Via implementing oracle

  • errors: Via implementing oracle

  • reentrancy: No reentrancy protection required at interface level

  • access: Implementation-defined (ORACLE_MANAGER_ROLE expected)

  • oracle: Configures the implementing oracle

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external;

Parameters

NameTypeDescription
_minPriceuint256New minimum price (18 decimals)
_maxPriceuint256New maximum price (18 decimals)

updateUsdcTolerance

Updates the allowed USDC deviation from $1.00 in basis points

Implementation-defined validation; caller is the router (ORACLE_MANAGER_ROLE)

Notes:

  • security: Restricted by the implementing oracle's access control

  • validation: Via implementing oracle

  • state-changes: Oracle USDC tolerance

  • events: Via implementing oracle

  • errors: Via implementing oracle

  • reentrancy: No reentrancy protection required at interface level

  • access: Implementation-defined (ORACLE_MANAGER_ROLE expected)

  • oracle: Configures the implementing oracle

function updateUsdcTolerance(uint256 newToleranceBps) external;

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance (e.g., 200 = 2%)

resetCircuitBreaker

Clears the circuit breaker and attempts to resume live prices

Implementation-defined validation; caller is the router (ORACLE_MANAGER_ROLE)

Notes:

  • security: Restricted by the implementing oracle's access control

  • validation: Via implementing oracle

  • state-changes: Oracle circuit-breaker state

  • events: Via implementing oracle

  • errors: Via implementing oracle

  • reentrancy: No reentrancy protection required at interface level

  • access: Implementation-defined

  • oracle: Configures the implementing oracle

function resetCircuitBreaker() external;

triggerCircuitBreaker

Manually triggers the circuit breaker to use fallback prices

Implementation-defined validation; caller is the router (ORACLE_MANAGER_ROLE)

Notes:

  • security: Restricted by the implementing oracle's access control

  • validation: Via implementing oracle

  • state-changes: Oracle circuit-breaker state

  • events: Via implementing oracle

  • errors: Via implementing oracle

  • reentrancy: No reentrancy protection required at interface level

  • access: Implementation-defined

  • oracle: Configures the implementing oracle

function triggerCircuitBreaker() external;

IMockAaveVault

Git Source

Title: IMockAaveVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the MockAaveVault (Aave V3 USDC yield vault)

Mirrors the external/public API of src/core/vaults/MockAaveVault.sol

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the Aave vault

Initializes the MockAaveVault contract with required addresses

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function initialize(
    address admin,
    address _usdc,
    address _aaveProvider,
    address _rewardsController,
    address _yieldShift,
    address _timelock,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_usdcaddressUSDC token address
_aaveProvideraddressAave PoolAddressesProvider
_rewardsControlleraddressAave RewardsController address
_yieldShiftaddressYieldShift contract address
_timelockaddressTimelock contract address
_treasuryaddressTreasury address

deployToAave

Deploy USDC to Aave V3 pool to earn yield

Deploys USDC to Aave V3 pool to earn yield

Notes:

  • security: Validates oracle price freshness, enforces exposure limits

  • validation: Validates amount > 0, checks max exposure limits

  • state-changes: Updates principalDeposited, transfers USDC, receives aUSDC

  • events: Emits DeployedToAave with operation details

  • errors: Throws WouldExceedLimit if exceeds maxAaveExposure

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to VAULT_MANAGER_ROLE

  • oracle: Requires fresh EUR/USD price for health validation

function deployToAave(uint256 amount) external returns (uint256 aTokensReceived);

Parameters

NameTypeDescription
amountuint256USDC amount to supply (6 decimals)

Returns

NameTypeDescription
aTokensReceiveduint256Amount of aUSDC received (6 decimals)

withdrawFromAave

Withdraw USDC from Aave V3 pool

Withdraws USDC from Aave V3 pool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function withdrawFromAave(uint256 amount) external returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
amountuint256Amount of aUSDC to withdraw (use type(uint256).max for all)

Returns

NameTypeDescription
usdcWithdrawnuint256Amount of USDC actually withdrawn

claimAaveRewards

Claim Aave rewards (if any)

Claims Aave rewards if any are available

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function claimAaveRewards() external returns (uint256 rewardsClaimed);

Returns

NameTypeDescription
rewardsClaimeduint256Claimed reward amount

harvestAaveYield

Harvest Aave yield and distribute via YieldShift

This function calls YieldShift.harvestAndDistributeAaveYield() to handle distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function harvestAaveYield() external returns (uint256 yieldHarvested);

Returns

NameTypeDescription
yieldHarvesteduint256Amount harvested

getAvailableYield

Calculate available yield for harvest

Calculates the amount of yield available for harvest

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAvailableYield() external view returns (uint256 available);

Returns

NameTypeDescription
availableuint256Amount of yield available

getYieldDistribution

Get yield distribution breakdown for current state

Returns the breakdown of yield distribution for current state

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getYieldDistribution()
    external
    view
    returns (uint256 protocolYield, uint256 userYield, uint256 hedgerYield);

Returns

NameTypeDescription
protocolYielduint256Protocol fee portion
userYielduint256Allocation to users
hedgerYielduint256Allocation to hedgers

getAaveBalance

Current aUSDC balance of the vault

Returns the current aUSDC balance of the vault

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAaveBalance() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The current aUSDC balance

getAccruedInterest

Accrued interest (same as available yield)

Returns the accrued interest (same as available yield)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAccruedInterest() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The accrued interest amount

getAaveAPY

Current Aave APY in basis points

Returns the current Aave APY in basis points

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAaveAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Current APY in basis points

getAavePositionDetails

Aave position details snapshot

Returns a snapshot of Aave position details

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAavePositionDetails()
    external
    view
    returns (uint256 principalDeposited_, uint256 currentBalance, uint256 aTokenBalance, uint256 lastUpdateTime);

Returns

NameTypeDescription
principalDeposited_uint256Principal USDC supplied
currentBalanceuint256Current aUSDC balance (1:1 underlying + interest)
aTokenBalanceuint256Alias for aUSDC balance
lastUpdateTimeuint256Timestamp of last harvest

getAaveMarketData

Aave market data snapshot

Returns Aave market data snapshot

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAaveMarketData()
    external
    view
    returns (uint256 supplyRate, uint256 utilizationRate, uint256 totalSupply, uint256 availableLiquidity);

Returns

NameTypeDescription
supplyRateuint256Current supply rate (bps)
utilizationRateuint256Utilization rate (bps)
totalSupplyuint256USDC total supply
availableLiquidityuint256Available USDC liquidity in Aave pool

checkAaveHealth

Basic Aave pool health and pause state

Returns basic Aave pool health and pause state

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function checkAaveHealth() external view returns (bool isHealthy, bool pauseStatus, uint256 lastUpdate);

Returns

NameTypeDescription
isHealthyboolTrue if pool considered healthy
pauseStatusboolWhether vault is paused
lastUpdateuint256Last harvest time

autoRebalance

Attempt auto-rebalancing allocation

Automatically rebalances allocation based on current market conditions and yield opportunities

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function autoRebalance() external returns (bool rebalanced, uint256 newAllocation);

Returns

NameTypeDescription
rebalancedboolWhether a rebalance decision was made
newAllocationuint256New target allocation (bps)

calculateOptimalAllocation

Compute optimal allocation and expected yield

Calculates the optimal allocation percentage and expected yield based on current market conditions

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function calculateOptimalAllocation() external view returns (uint256 optimalAllocation, uint256 expectedYield);

Returns

NameTypeDescription
optimalAllocationuint256Target allocation (bps)
expectedYielduint256Expected yield proxy

setMaxAaveExposure

Update max exposure to Aave

Sets the maximum USDC exposure limit for Aave protocol interactions

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function setMaxAaveExposure(uint256 _maxExposure) external;

Parameters

NameTypeDescription
_maxExposureuint256New max USDC exposure

emergencyWithdrawFromAave

Emergency: withdraw all from Aave

Emergency function to withdraw all funds from Aave protocol in case of emergency

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyWithdrawFromAave() external returns (uint256 amountWithdrawn);

Returns

NameTypeDescription
amountWithdrawnuint256Amount withdrawn

getRiskMetrics

Risk metrics snapshot

Returns current risk metrics including exposure ratio and risk scores

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getRiskMetrics()
    external
    view
    returns (uint256 exposureRatio, uint256 concentrationRisk, uint256 liquidityRisk);

Returns

NameTypeDescription
exposureRatiouint256% of assets in Aave (bps)
concentrationRiskuint256Heuristic risk score (1-3)
liquidityRiskuint256Heuristic risk score (1-3)

updateAaveParameters

Update vault parameters

Updates key vault parameters including harvest threshold, yield fee, and rebalance threshold

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateAaveParameters(uint256 newHarvestThreshold, uint256 newYieldFee, uint256 newRebalanceThreshold)
    external;

Parameters

NameTypeDescription
newHarvestThresholduint256Min yield to harvest
newYieldFeeuint256Protocol fee on yield (bps)
newRebalanceThresholduint256Rebalance threshold (bps)

updateYieldShift

Updates the YieldShift dependency address.

Rotates the YieldShift contract reference used for harvested-yield routing.

Notes:

  • security: Intended for governance-only execution in implementation.

  • validation: Implementations must reject zero/invalid addresses.

  • state-changes: Updates stored YieldShift dependency.

  • events: Emits parameter-update event in implementation.

  • errors: Reverts on unauthorized access or invalid address.

  • reentrancy: Configuration setter; no user balance mutation expected.

  • access: Access controlled by implementation (governance role).

  • oracle: No oracle dependencies.

function updateYieldShift(address newYieldShift) external;

Parameters

NameTypeDescription
newYieldShiftaddressNew YieldShift address.

setYieldVaultId

Sets the target vault id used for YieldShift routing.

Updates the destination vault id for yield forwarding flows.

Notes:

  • security: Intended for governance-only execution in implementation.

  • validation: Implementations should reject zero/invalid vault ids.

  • state-changes: Updates stored yieldVaultId.

  • events: Emits parameter-update event in implementation.

  • errors: Reverts on unauthorized access or invalid vault id.

  • reentrancy: Configuration setter; no user balance mutation expected.

  • access: Access controlled by implementation (governance role).

  • oracle: No oracle dependencies.

function setYieldVaultId(uint256 newYieldVaultId) external;

Parameters

NameTypeDescription
newYieldVaultIduint256Vault id in stQEUROFactory.

getAaveConfig

Aave config snapshot

Returns current Aave configuration including pool address, token address, and key parameters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getAaveConfig()
    external
    view
    returns (address aavePool_, address aUSDC_, uint256 harvestThreshold_, uint256 yieldFee_, uint256 maxExposure_);

Returns

NameTypeDescription
aavePool_addressAave Pool address
aUSDC_addressaUSDC token address
harvestThreshold_uint256Current harvest threshold
yieldFee_uint256Current yield fee (bps)
maxExposure_uint256Max Aave exposure

toggleEmergencyMode

Toggle emergency mode

Enables or disables emergency mode with a reason for the action

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function toggleEmergencyMode(bool enabled, string calldata reason) external;

Parameters

NameTypeDescription
enabledboolNew emergency flag
reasonstringReason string

pause

Pause the vault

Pauses all vault operations for emergency situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external;

unpause

Unpause the vault

Resumes vault operations after being paused

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external;

recoverToken

Recover ERC20 tokens sent by mistake

Allows recovery of ERC20 tokens accidentally sent to the contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address
amountuint256Amount to transfer

recoverETH

Recover ETH sent by mistake

Allows recovery of ETH accidentally sent to the contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

hasRole

Check if an account has a specific role

Returns true if the account has the specified role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasRole(bytes32 role, address account) external view returns (bool);

Parameters

NameTypeDescription
rolebytes32The role to check
accountaddressThe account to check

Returns

NameTypeDescription
<none>boolbool True if the account has the role, false otherwise

getRoleAdmin

Get the admin role for a specific role

Returns the admin role that controls the specified role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getRoleAdmin(bytes32 role) external view returns (bytes32);

Parameters

NameTypeDescription
rolebytes32The role to get the admin for

Returns

NameTypeDescription
<none>bytes32bytes32 The admin role

grantRole

Grant a role to an account

Grants the specified role to the account

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function grantRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to grant
accountaddressThe account to grant the role to

revokeRole

Revoke a role from an account

Revokes the specified role from the account

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function revokeRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to revoke
accountaddressThe account to revoke the role from

renounceRole

Renounce a role

Renounces the specified role from the caller

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function renounceRole(bytes32 role, address callerConfirmation) external;

Parameters

NameTypeDescription
rolebytes32The role to renounce
callerConfirmationaddressConfirmation that the caller is renouncing the role

paused

Check if the contract is paused

Returns true if the contract is paused, false otherwise

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolbool True if paused, false otherwise

upgradeTo

Upgrade the contract implementation

Upgrades the contract to a new implementation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeTo(address newImplementation) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

upgradeToAndCall

Upgrade the contract implementation and call a function

Upgrades the contract to a new implementation and calls a function

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeToAndCall(address newImplementation, bytes memory data) external payable;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
databytesData to call on the new implementation

GOVERNANCE_ROLE

Get the governance role identifier

Returns the governance role identifier

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function GOVERNANCE_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The governance role identifier

VAULT_MANAGER_ROLE

Get the vault manager role identifier

Returns the vault manager role identifier

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function VAULT_MANAGER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The vault manager role identifier

EMERGENCY_ROLE

Get the emergency role identifier

Returns the emergency role identifier

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function EMERGENCY_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The emergency role identifier

UPGRADER_ROLE

Get the upgrader role identifier

Returns the upgrader role identifier

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The upgrader role identifier

usdc

Get the USDC token address

Returns the address of the USDC token contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The USDC token address

aUSDC

Get the aUSDC token address

Returns the address of the aUSDC token contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function aUSDC() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The aUSDC token address

aavePool

Get the Aave pool address

Returns the address of the Aave pool contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function aavePool() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The Aave pool address

aaveProvider

Get the Aave provider address

Returns the address of the Aave provider contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function aaveProvider() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The Aave provider address

rewardsController

Get the rewards controller address

Returns the address of the rewards controller contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function rewardsController() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The rewards controller address

yieldShift

Get the yield shift address

Returns the address of the yield shift contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function yieldShift() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress The yield shift address

maxAaveExposure

Get the maximum Aave exposure

Returns the maximum amount that can be deposited to Aave

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function maxAaveExposure() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The maximum Aave exposure

harvestThreshold

Get the harvest threshold

Returns the minimum amount required to trigger a harvest

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function harvestThreshold() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The harvest threshold

yieldFee

Get the yield fee

Returns the fee percentage charged on harvested yield

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function yieldFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The yield fee in basis points

yieldVaultId

Returns the configured YieldShift vault id used by this Aave vault.

Exposes the cached vault id destination for YieldShift forwarding.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function yieldVaultId() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The target vault id.

rebalanceThreshold

Get the rebalance threshold

Returns the threshold for triggering rebalancing

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function rebalanceThreshold() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The rebalance threshold

principalDeposited

Get the principal deposited amount

Returns the total amount of principal deposited to Aave

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function principalDeposited() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The principal deposited amount

lastHarvestTime

Get the last harvest time

Returns the timestamp of the last harvest

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function lastHarvestTime() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The last harvest time

totalYieldHarvested

Get the total yield harvested

Returns the total amount of yield harvested from Aave

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalYieldHarvested() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The total yield harvested

totalFeesCollected

Get the total fees collected

Returns the total amount of fees collected

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalFeesCollected() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The total fees collected

utilizationLimit

Get the utilization limit

Returns the maximum utilization rate allowed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function utilizationLimit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The utilization limit

emergencyExitThreshold

Get the emergency exit threshold

Returns the threshold for triggering emergency exit

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyExitThreshold() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The emergency exit threshold

emergencyMode

Get the emergency mode status

Returns true if the contract is in emergency mode

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyMode() external view returns (bool);

Returns

NameTypeDescription
<none>boolbool True if in emergency mode, false otherwise

IOracle

Git Source

Title: IOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Generic interface for Quantillon Protocol oracle contracts

This interface is oracle-agnostic and can work with Chainlink, Stork, or any other oracle implementation The OracleRouter implements this interface and delegates to the active oracle (Chainlink or Stork)

Note: security-contact: team@quantillon.money

Functions

getEurUsdPrice

Gets the current EUR/USD price with validation

Retrieves and validates EUR/USD price from the active oracle with freshness checks

Notes:

  • security: Validates price freshness and bounds before returning

  • validation: Checks price staleness and circuit breaker state

  • state-changes: May update lastValidPrice if price is valid

  • events: No events emitted

  • errors: No errors thrown, returns isValid=false for invalid prices

  • reentrancy: Not protected - read-only operation

  • access: Public - no access restrictions

  • oracle: Queries active oracle (Chainlink or Stork) for EUR/USD price

function getEurUsdPrice() external returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if fresh and within acceptable bounds

getUsdcUsdPrice

Gets the current USDC/USD price with validation

Retrieves and validates USDC/USD price from the active oracle with tolerance checks

Notes:

  • security: Validates price is within tolerance of $1.00

  • validation: Checks price staleness and deviation from $1.00

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns isValid=false for invalid prices

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Queries active oracle (Chainlink or Stork) for USDC/USD price

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals (should be ~1e18)
isValidboolTrue if fresh and within tolerance

getOracleHealth

Returns overall oracle health signals

Checks the health status of both price feeds and overall oracle state

Notes:

  • security: Provides health status for monitoring and circuit breaker decisions

  • validation: Checks feed freshness, circuit breaker state, and pause status

  • state-changes: May update internal state during health check

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - read-only operation

  • access: Public - no access restrictions

  • oracle: Queries active oracle health status for both feeds

function getOracleHealth() external returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthyboolTrue if both feeds are fresh, circuit breaker is off, and not paused
eurUsdFreshboolTrue if EUR/USD feed is fresh
usdcUsdFreshboolTrue if USDC/USD feed is fresh

getEurUsdDetails

Detailed information about the EUR/USD price

Provides comprehensive EUR/USD price information including validation status

Notes:

  • security: Provides detailed price information for debugging and monitoring

  • validation: Checks price freshness and bounds validation

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - read-only operation

  • access: Public - no access restrictions

  • oracle: Queries active oracle for detailed EUR/USD price information

function getEurUsdDetails()
    external
    view
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Timestamp reported by the underlying EUR/USD feed
isStaleboolTrue if the feed data is stale
withinBoundsboolTrue if within configured min/max bounds

getOracleConfig

Current configuration and circuit breaker state

Returns current oracle configuration parameters and circuit breaker status

Notes:

  • security: Returns configuration for security monitoring

  • validation: No validation - read-only configuration

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Returns configuration from active oracle

function getOracleConfig()
    external
    view
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum accepted EUR/USD price
maxPriceuint256Maximum accepted EUR/USD price
maxStalenessuint256Maximum allowed staleness in seconds
usdcToleranceuint256USDC tolerance in basis points
circuitBreakerActiveboolTrue if circuit breaker is triggered

getPriceFeedAddresses

Addresses and decimals of the underlying feeds

Returns the addresses and decimal precision of both price feeds

Notes:

  • security: Returns feed addresses for verification

  • validation: No validation - read-only information

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Returns feed addresses from active oracle

function getPriceFeedAddresses()
    external
    view
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD feed address
usdcUsdFeedAddressaddressUSDC/USD feed address
eurUsdDecimalsuint8EUR/USD feed decimals
usdcUsdDecimalsuint8USDC/USD feed decimals

checkPriceFeedConnectivity

Connectivity check for both feeds

Tests connectivity to both price feeds and returns latest round information

Notes:

  • security: Tests feed connectivity for health monitoring

  • validation: No validation - connectivity test only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns false for disconnected feeds

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Tests connectivity to active oracle feeds

function checkPriceFeedConnectivity()
    external
    view
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedboolTrue if EUR/USD feed responds
usdcUsdConnectedboolTrue if USDC/USD feed responds
eurUsdLatestRounduint80Latest round ID for EUR/USD (0 for non-round-based oracles)
usdcUsdLatestRounduint80Latest round ID for USDC/USD (0 for non-round-based oracles)

IQEUROToken

Git Source

Title: IQEUROToken

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Read-only interface for the QEURO token

Exposes ERC20 metadata and helper views used by integrators

Note: security-contact: team@quantillon.money

Functions

name

Token name

Returns the name of the QEURO token

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function name() external view returns (string memory);

Returns

NameTypeDescription
<none>stringname The token name string

symbol

Token symbol

Returns the symbol of the QEURO token

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function symbol() external view returns (string memory);

Returns

NameTypeDescription
<none>stringsymbol The token symbol string

decimals

Token decimals (always 18)

Returns the number of decimals used by the token

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function decimals() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8decimals The number of decimals (always 18)

totalSupply

Total token supply

Returns the total supply of QEURO tokens

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalSupply() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256totalSupply The total supply (18 decimals)

balanceOf

Balance of an account

Returns the token balance of the specified account

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function balanceOf(address account) external view returns (uint256);

Parameters

NameTypeDescription
accountaddressAddress to query

Returns

NameTypeDescription
<none>uint256balance The token balance (18 decimals)

isMinter

Whether an address has the minter role

Checks if the specified account has the MINTER_ROLE

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isMinter(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>boolisMinter True if the account has the minter role

isBurner

Whether an address has the burner role

Checks if the specified account has the BURNER_ROLE

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isBurner(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>boolisBurner True if the account has the burner role

getSupplyUtilization

Percentage of max supply utilized (basis points)

Returns the percentage of maximum supply currently in circulation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getSupplyUtilization() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256utilization Percentage of max supply utilized (basis points)

getTokenInfo

Aggregated token information snapshot

Returns comprehensive token information in a single call

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getTokenInfo()
    external
    view
    returns (
        string memory name_,
        string memory symbol_,
        uint8 decimals_,
        uint256 totalSupply_,
        uint256 maxSupply_,
        bool isPaused_,
        bool whitelistEnabled_,
        uint256 mintRateLimit_,
        uint256 burnRateLimit_
    );

Returns

NameTypeDescription
name_stringToken name
symbol_stringToken symbol
decimals_uint8Token decimals
totalSupply_uint256Current total supply
maxSupply_uint256Maximum supply cap
isPaused_boolWhether the token is paused
whitelistEnabled_boolWhether whitelist mode is active
mintRateLimit_uint256Current mint rate limit per hour
burnRateLimit_uint256Current burn rate limit per hour

initialize

Initialize the QEURO token contract

Sets up initial roles and configuration for the token

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function initialize(address admin, address vault, address timelock, address treasury, address feeCollector) external;

Parameters

NameTypeDescription
adminaddressAddress of the admin role
vaultaddressAddress of the vault contract
timelockaddressAddress of the timelock contract
treasuryaddressTreasury address
feeCollectoraddressAddress of the fee collector contract

mint

Mint new QEURO tokens to an address

Creates new tokens and adds them to the specified address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function mint(address to, uint256 amount) external;

Parameters

NameTypeDescription
toaddressAddress to receive the minted tokens
amountuint256Amount of tokens to mint (18 decimals)

burn

Burn QEURO tokens from an address

Destroys tokens from the specified address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function burn(address from, uint256 amount) external;

Parameters

NameTypeDescription
fromaddressAddress to burn tokens from
amountuint256Amount of tokens to burn (18 decimals)

batchMint

Mint new QEURO tokens to multiple addresses

Creates new tokens and distributes them to multiple recipients

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchMint(address[] calldata recipients, uint256[] calldata amounts) external;

Parameters

NameTypeDescription
recipientsaddress[]Array of addresses to receive the minted tokens
amountsuint256[]Array of amounts to mint for each recipient (18 decimals)

batchBurn

Burn QEURO tokens from multiple addresses

Destroys tokens from multiple addresses

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by flashLoanProtection modifier

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchBurn(address[] calldata froms, uint256[] calldata amounts) external;

Parameters

NameTypeDescription
fromsaddress[]Array of addresses to burn tokens from
amountsuint256[]Array of amounts to burn from each address (18 decimals)

batchTransfer

Transfer QEURO tokens to multiple addresses

Transfers tokens from the caller to multiple recipients

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) external returns (bool);

Parameters

NameTypeDescription
recipientsaddress[]Array of addresses to receive the tokens
amountsuint256[]Array of amounts to transfer to each recipient (18 decimals)

Returns

NameTypeDescription
<none>boolsuccess True if all transfers were successful

updateRateLimits

Update rate limits for minting and burning operations

Modifies the maximum amount of tokens that can be minted or burned per hour

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateRateLimits(uint256 newMintLimit, uint256 newBurnLimit) external;

Parameters

NameTypeDescription
newMintLimituint256New maximum amount of tokens that can be minted per hour (18 decimals)
newBurnLimituint256New maximum amount of tokens that can be burned per hour (18 decimals)

blacklistAddress

Add an address to the blacklist with a reason

Prevents the specified address from participating in token operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function blacklistAddress(address account, string memory reason) external;

Parameters

NameTypeDescription
accountaddressAddress to blacklist
reasonstringReason for blacklisting the address

unblacklistAddress

Remove an address from the blacklist

Allows the specified address to participate in token operations again

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unblacklistAddress(address account) external;

Parameters

NameTypeDescription
accountaddressAddress to remove from blacklist

whitelistAddress

Add an address to the whitelist

Allows the specified address to participate in token operations when whitelist mode is enabled

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function whitelistAddress(address account) external;

Parameters

NameTypeDescription
accountaddressAddress to whitelist

unwhitelistAddress

Remove an address from the whitelist

Prevents the specified address from participating in token operations when whitelist mode is enabled

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unwhitelistAddress(address account) external;

Parameters

NameTypeDescription
accountaddressAddress to remove from whitelist

toggleWhitelistMode

Toggle whitelist mode on or off

When enabled, only whitelisted addresses can participate in token operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function toggleWhitelistMode(bool enabled) external;

Parameters

NameTypeDescription
enabledboolTrue to enable whitelist mode, false to disable

batchBlacklistAddresses

Add multiple addresses to the blacklist with reasons

Batch operation to blacklist multiple addresses efficiently

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchBlacklistAddresses(address[] calldata accounts, string[] calldata reasons) external;

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to blacklist
reasonsstring[]Array of reasons for blacklisting each address

batchUnblacklistAddresses

Remove multiple addresses from the blacklist

Batch operation to unblacklist multiple addresses efficiently

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchUnblacklistAddresses(address[] calldata accounts) external;

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to remove from blacklist

batchWhitelistAddresses

Add multiple addresses to the whitelist

Batch operation to whitelist multiple addresses efficiently

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchWhitelistAddresses(address[] calldata accounts) external;

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to whitelist

batchUnwhitelistAddresses

Remove multiple addresses from the whitelist

Batch operation to unwhitelist multiple addresses efficiently

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function batchUnwhitelistAddresses(address[] calldata accounts) external;

Parameters

NameTypeDescription
accountsaddress[]Array of addresses to remove from whitelist

updateMinPricePrecision

Update the minimum price precision for oracle feeds

Sets the minimum number of decimal places required for price feeds

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateMinPricePrecision(uint256 newPrecision) external;

Parameters

NameTypeDescription
newPrecisionuint256New minimum precision value (number of decimal places)

normalizePrice

Normalize price from different decimal precisions to 18 decimals

Converts price from source feed decimals to standard 18 decimal format

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function normalizePrice(uint256 price, uint8 feedDecimals) external pure returns (uint256);

Parameters

NameTypeDescription
priceuint256Price value to normalize
feedDecimalsuint8Number of decimal places in the source feed

Returns

NameTypeDescription
<none>uint256normalizedPrice Price normalized to 18 decimals

validatePricePrecision

Validate if price precision meets minimum requirements

Checks if the price feed has sufficient decimal precision

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function validatePricePrecision(uint256 price, uint8 feedDecimals) external view returns (bool);

Parameters

NameTypeDescription
priceuint256Price value to validate
feedDecimalsuint8Number of decimal places in the price feed

Returns

NameTypeDescription
<none>boolisValid True if precision meets minimum requirements

pause

Pause all token operations

Emergency function to halt all token transfers, minting, and burning

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external;

unpause

Unpause all token operations

Resumes normal token operations after emergency pause

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external;

recoverToken

Recover accidentally sent tokens

Allows recovery of ERC20 tokens sent to the contract by mistake

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressAddress of the token to recover
amountuint256Amount of tokens to recover

recoverETH

Recover accidentally sent ETH

Allows recovery of ETH sent to the contract by mistake

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

updateMaxSupply

Update the maximum supply of QEURO tokens

Sets a new maximum supply limit for the token

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateMaxSupply(uint256 newMaxSupply) external;

Parameters

NameTypeDescription
newMaxSupplyuint256New maximum supply limit (18 decimals)

transfer

Transfer QEURO tokens to another address

Standard ERC20 transfer function with compliance checks

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function transfer(address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
toaddressAddress to transfer tokens to
amountuint256Amount of tokens to transfer (18 decimals)

Returns

NameTypeDescription
<none>boolsuccess True if transfer was successful

allowance

Get the allowance for a spender

Returns the amount of tokens that a spender is allowed to transfer

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function allowance(address owner, address spender) external view returns (uint256);

Parameters

NameTypeDescription
owneraddressAddress of the token owner
spenderaddressAddress of the spender

Returns

NameTypeDescription
<none>uint256allowance Amount of tokens the spender can transfer (18 decimals)

approve

Approve a spender to transfer tokens

Sets the allowance for a spender to transfer tokens on behalf of the caller

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function approve(address spender, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
spenderaddressAddress of the spender to approve
amountuint256Amount of tokens to approve (18 decimals)

Returns

NameTypeDescription
<none>boolsuccess True if approval was successful

transferFrom

Transfer tokens from one address to another

Standard ERC20 transferFrom function with compliance checks

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function transferFrom(address from, address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
fromaddressAddress to transfer tokens from
toaddressAddress to transfer tokens to
amountuint256Amount of tokens to transfer (18 decimals)

Returns

NameTypeDescription
<none>boolsuccess True if transfer was successful

hasRole

Check if an address has a specific role

Returns true if the account has the specified role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasRole(bytes32 role, address account) external view returns (bool);

Parameters

NameTypeDescription
rolebytes32Role to check for
accountaddressAddress to check

Returns

NameTypeDescription
<none>boolhasRole True if the account has the role

getRoleAdmin

Get the admin role for a specific role

Returns the role that is the admin of the given role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getRoleAdmin(bytes32 role) external view returns (bytes32);

Parameters

NameTypeDescription
rolebytes32Role to get admin for

Returns

NameTypeDescription
<none>bytes32adminRole The admin role

grantRole

Grant a role to an address

Assigns the specified role to the given account

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function grantRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32Role to grant
accountaddressAddress to grant the role to

revokeRole

Revoke a role from an address

Removes the specified role from the given account

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function revokeRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32Role to revoke
accountaddressAddress to revoke the role from

renounceRole

Renounce a role

Removes the specified role from the caller

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function renounceRole(bytes32 role, address callerConfirmation) external;

Parameters

NameTypeDescription
rolebytes32Role to renounce
callerConfirmationaddressAddress of the caller (for security)

paused

Check if the contract is paused

Returns true if all token operations are paused

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolisPaused True if the contract is paused

upgradeTo

Upgrade the contract implementation

Upgrades to a new implementation address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeTo(address newImplementation) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

upgradeToAndCall

Upgrade the contract implementation and call a function

Upgrades to a new implementation and executes a function call

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeToAndCall(address newImplementation, bytes memory data) external payable;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
databytesEncoded function call data

MINTER_ROLE

Get the MINTER_ROLE constant

Returns the role hash for minters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MINTER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32role The MINTER_ROLE bytes32 value

BURNER_ROLE

Get the BURNER_ROLE constant

Returns the role hash for burners

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function BURNER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32role The BURNER_ROLE bytes32 value

PAUSER_ROLE

Get the PAUSER_ROLE constant

Returns the role hash for pausers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function PAUSER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32role The PAUSER_ROLE bytes32 value

UPGRADER_ROLE

Get the UPGRADER_ROLE constant

Returns the role hash for upgraders

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32role The UPGRADER_ROLE bytes32 value

COMPLIANCE_ROLE

Get the COMPLIANCE_ROLE constant

Returns the role hash for compliance officers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function COMPLIANCE_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32role The COMPLIANCE_ROLE bytes32 value

DEFAULT_MAX_SUPPLY

Get the DEFAULT_MAX_SUPPLY constant

Returns the default maximum supply limit

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function DEFAULT_MAX_SUPPLY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256maxSupply The default maximum supply (18 decimals)

MAX_RATE_LIMIT

Get the MAX_RATE_LIMIT constant

Returns the maximum rate limit value

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MAX_RATE_LIMIT() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256maxLimit The maximum rate limit (18 decimals)

PRECISION

Get the PRECISION constant

Returns the precision value used for calculations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function PRECISION() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256precision The precision value (18 decimals)

maxSupply

Get the current maximum supply limit

Returns the maximum number of tokens that can be minted

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function maxSupply() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256maxSupply Current maximum supply limit (18 decimals)

mintRateLimit

Get the current mint rate limit

Returns the maximum amount of tokens that can be minted per hour

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function mintRateLimit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256mintLimit Current mint rate limit (18 decimals)

burnRateLimit

Get the current burn rate limit

Returns the maximum amount of tokens that can be burned per hour

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function burnRateLimit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256burnLimit Current burn rate limit (18 decimals)

currentHourMinted

Get the amount minted in the current hour

Returns the total amount of tokens minted in the current rate limit window

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function currentHourMinted() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256minted Current hour minted amount (18 decimals)

currentHourBurned

Get the amount burned in the current hour

Returns the total amount of tokens burned in the current rate limit window

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function currentHourBurned() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256burned Current hour burned amount (18 decimals)

lastRateLimitReset

Get the timestamp of the last rate limit reset

Returns when the rate limit counters were last reset

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function lastRateLimitReset() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256resetTime Timestamp of last rate limit reset

isBlacklisted

Check if an address is blacklisted

Returns true if the address is on the blacklist

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isBlacklisted(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>boolisBlacklisted True if the address is blacklisted

isWhitelisted

Check if an address is whitelisted

Returns true if the address is on the whitelist

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isWhitelisted(address account) external view returns (bool);

Parameters

NameTypeDescription
accountaddressAddress to check

Returns

NameTypeDescription
<none>boolisWhitelisted True if the address is whitelisted

whitelistEnabled

Check if whitelist mode is enabled

Returns true if whitelist mode is active

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function whitelistEnabled() external view returns (bool);

Returns

NameTypeDescription
<none>boolenabled True if whitelist mode is enabled

minPricePrecision

Get the minimum price precision requirement

Returns the minimum number of decimal places required for price feeds

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function minPricePrecision() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256precision Minimum price precision value

IQuantillonVault

Git Source

Title: IQuantillonVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the Quantillon vault managing QEURO mint/redeem against USDC

Exposes core swap functions, views, governance, emergency, and recovery

Note: security-contact: team@quantillon.money

Functions

signedExecutionEnabled

Whether signed execution is enabled by governance.

Reads the vault's configured execution mode.

Notes:

  • security: Read-only; does not grant settlement authority.

  • validation: No input validation required.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: Does not read a price.

function signedExecutionEnabled() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue when signed settlement is enabled.

executeWithQuote

Execute a permitted operation with its exact signed authorization.

Delegates to the signed settlement extension with the original caller.

Notes:

  • security: Preserves settlement accounting and caller binding.

  • validation: Checks signatures, nonce, expiry, amounts and aggregate capacity.

  • state-changes: Consumes the quote and settles the operation atomically.

  • events: QuoteSettled and underlying settlement events.

  • errors: Reverts on invalid authorization or protocol guards.

  • reentrancy: Retains the consuming operation's reentrancy guard.

  • access: Caller bound by the signed quote.

  • oracle: Signed execution and independently checked reference reports.

function executeWithQuote(bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesEncoded permitted vault operation, bound by the quote hash.
authorizationbytesEncoded quote, reference and capacity reports with signatures.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the underlying operation.

preparePoolQuote

Prepare an authenticated UserPool settlement for its original user.

Establishes the signed context consumed by the pool route in the same transaction.

Notes:

  • security: Only the configured UserPool may establish this context.

  • validation: Validates authorization and original user binding.

  • state-changes: Establishes the active pool settlement context.

  • events: Underlying report acceptance events.

  • errors: Reverts on unauthorized callers, paused state or invalid authorization.

  • reentrancy: The signed context cannot be reused by another route.

  • access: Configured UserPool.

  • oracle: Signed reference and capacity reports.

function preparePoolQuote(address user, bytes calldata callData, bytes calldata authorization) external;

Parameters

NameTypeDescription
useraddressOriginal UserPool user bound by the quote.
callDatabytesEncoded UserPool operation bound by the quote hash.
authorizationbytesEncoded signed quote, reference and capacity authorization.

finishPoolQuote

Finalize the authenticated UserPool settlement.

Requires the prepared conversion to have been consumed.

Notes:

  • security: Only the configured UserPool can finalize its active context.

  • validation: Verifies completion of the prepared settlement.

  • state-changes: Clears the active signed settlement context.

  • events: QuoteSettled for the completed operation.

  • errors: Reverts on unauthorized callers or incomplete settlement.

  • reentrancy: Clears the context within the atomic pool operation.

  • access: Configured UserPool.

  • oracle: Uses the reference accepted during preparation.

function finishPoolQuote() external;

initialize

Initializes the vault

Sets up the vault with initial configuration and assigns roles to admin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _oracle,
    address _hedgerPool,
    address _userPool,
    address _timelock,
    address _feeCollector
) external;

Parameters

NameTypeDescription
adminaddressAdmin address receiving roles
_qeuroaddressQEURO token address
_usdcaddressUSDC token address
_oracleaddressOracle contract address
_hedgerPooladdressHedgerPool contract address
_userPooladdressUserPool contract address
_timelockaddressTimelock contract address
_feeCollectoraddressFeeCollector contract address

mintQEURO

Mints QEURO by swapping USDC

Converts USDC to QEURO using current oracle price with slippage protection

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function mintQEURO(uint256 usdcAmount, uint256 minQeuroOut) external;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to swap
minQeuroOutuint256Minimum QEURO expected (slippage protection)

mintQEUROToVault

Mints QEURO and routes resulting principal toward a specific vault id.

Variant of mint flow with explicit external-vault routing control.

Notes:

  • security: Protected by implementation pause/reentrancy controls.

  • validation: Implementations validate vault id state and slippage/oracle checks.

  • state-changes: Updates mint accounting and optional external-vault principal allocation.

  • events: Emits mint and potentially vault-deployment events in implementation.

  • errors: Reverts on invalid routing, slippage, oracle, or collateralization failures.

  • reentrancy: Implementation is expected to guard with nonReentrant.

  • access: Public.

  • oracle: Requires fresh oracle price data.

function mintQEUROToVault(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId) external;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to swap.
minQeuroOutuint256Minimum QEURO expected (slippage protection).
vaultIduint256Target vault id for principal routing (0 disables explicit routing).

mintAndStakeQEURO

Mints QEURO and stakes it into the stQEURO token for a selected vault id.

One-step user flow combining mint and stake operations.

Notes:

  • security: Protected by implementation pause/reentrancy controls.

  • validation: Implementations validate vault/token availability and slippage constraints.

  • state-changes: Updates mint and staking state across integrated contracts.

  • events: Emits mint/staking events in implementation and downstream contracts.

  • errors: Reverts on invalid vault, slippage, or integration failures.

  • reentrancy: Implementation is expected to guard with nonReentrant.

  • access: Public.

  • oracle: Requires fresh oracle price data for mint.

function mintAndStakeQEURO(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId, uint256 minStQEUROOut)
    external
    returns (uint256 qeuroMinted, uint256 stQEUROMinted);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to swap.
minQeuroOutuint256Minimum QEURO expected from mint.
vaultIduint256Target vault id for mint routing and stQEURO token selection.
minStQEUROOutuint256Minimum stQEURO expected from staking.

Returns

NameTypeDescription
qeuroMinteduint256QEURO minted before staking.
stQEUROMinteduint256stQEURO minted and returned to user.

creditVaultYield

Credits harvested user yield into a vault-specific stQEURO series.

Converts harvested USDC yield into QEURO using the vault minting path and deposits the resulting backing directly into the target stQEURO vault.

Notes:

  • security: Restricted in implementation to authorized yield distributors and validated vault bindings.

  • validation: Implementations validate vault registration, non-zero amounts, and fee/oracle constraints before crediting yield.

  • state-changes: Pulls or accounts for harvested USDC, mints QEURO backing, updates protocol accounting, and increases the target vault's asset balance.

  • events: Emits implementation-defined yield crediting and mint-related events.

  • errors: Reverts on invalid vault ids, zero amounts, oracle failures, or downstream minting/transfer failures.

  • reentrancy: Implementation is expected to guard integrated token-transfer flows.

  • access: Restricted in implementation to a dedicated yield-distributor permission.

  • oracle: Requires fresh oracle price data for USDC-to-QEURO conversion.

function creditVaultYield(uint256 vaultId, uint256 usdcAmount) external returns (uint256 qeuroMinted);

Parameters

NameTypeDescription
vaultIduint256Vault identifier receiving the compounded yield.
usdcAmountuint256User-side harvested yield in USDC.

Returns

NameTypeDescription
qeuroMinteduint256Net QEURO minted into the stQEURO vault.

redeemQEURO

Redeems QEURO for USDC

Converts QEURO (18 decimals) to USDC (6 decimals) using oracle price

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function redeemQEURO(uint256 qeuroAmount, uint256 minUsdcOut) external;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to swap
minUsdcOutuint256Minimum USDC expected

updateParameters

Updates vault parameters

Allows governance to update fee parameters for minting and redemption

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateParameters(uint256 _mintFee, uint256 _redemptionFee) external;

Parameters

NameTypeDescription
_mintFeeuint256New minting fee (1e18-scaled, where 1e18 = 100%)
_redemptionFeeuint256New redemption fee (1e18-scaled, where 1e18 = 100%)

updateOracle

Updates the oracle address

Allows governance to update the price oracle used for conversions

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateOracle(address _oracle) external;

Parameters

NameTypeDescription
_oracleaddressNew oracle address

withdrawProtocolFees

Withdraws accumulated protocol fees

Allows governance to withdraw accumulated fees to specified address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function withdrawProtocolFees(address to) external;

Parameters

NameTypeDescription
toaddressRecipient address

pause

Pauses the vault

Emergency function to pause all vault operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external;

unpause

Unpauses the vault

Resumes all vault operations after emergency pause

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external;

recoverToken

Recovers ERC20 tokens sent by mistake

Allows governance to recover accidentally sent ERC20 tokens to treasury

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address
amountuint256Amount to transfer

recoverETH

Recovers ETH sent by mistake

Allows governance to recover accidentally sent ETH

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

hasRole

Checks if an account has a specific role

Returns true if the account has been granted the role

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check roles

  • oracle: No oracle dependencies

function hasRole(bytes32 role, address account) external view returns (bool);

Parameters

NameTypeDescription
rolebytes32The role to check
accountaddressThe account to check

Returns

NameTypeDescription
<none>boolTrue if the account has the role

getRoleAdmin

Gets the admin role for a given role

Returns the role that is the admin of the given role

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query role admin

  • oracle: No oracle dependencies

function getRoleAdmin(bytes32 role) external view returns (bytes32);

Parameters

NameTypeDescription
rolebytes32The role to get admin for

Returns

NameTypeDescription
<none>bytes32The admin role

grantRole

Grants a role to an account

Can only be called by an account with the admin role

Notes:

  • security: Validates caller has admin role for the specified role

  • validation: Validates account is not address(0)

  • state-changes: Grants role to account

  • events: Emits RoleGranted event

  • errors: Throws AccessControlUnauthorizedAccount if caller lacks admin role

  • reentrancy: Not protected - no external calls

  • access: Restricted to role admin

  • oracle: No oracle dependencies

function grantRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to grant
accountaddressThe account to grant the role to

revokeRole

Revokes a role from an account

Can only be called by an account with the admin role

Notes:

  • security: Validates caller has admin role for the specified role

  • validation: Validates account is not address(0)

  • state-changes: Revokes role from account

  • events: Emits RoleRevoked event

  • errors: Throws AccessControlUnauthorizedAccount if caller lacks admin role

  • reentrancy: Not protected - no external calls

  • access: Restricted to role admin

  • oracle: No oracle dependencies

function revokeRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to revoke
accountaddressThe account to revoke the role from

renounceRole

Renounces a role from the caller

The caller gives up their own role

Notes:

  • security: Validates caller is renouncing their own role

  • validation: Validates callerConfirmation matches msg.sender

  • state-changes: Revokes role from caller

  • events: Emits RoleRevoked event

  • errors: Throws AccessControlBadConfirmation if callerConfirmation != msg.sender

  • reentrancy: Not protected - no external calls

  • access: Public - anyone can renounce their own roles

  • oracle: No oracle dependencies

function renounceRole(bytes32 role, address callerConfirmation) external;

Parameters

NameTypeDescription
rolebytes32The role to renounce
callerConfirmationaddressConfirmation that the caller is renouncing their own role

paused

Checks if the contract is paused

Returns true if the contract is currently paused

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check pause status

  • oracle: No oracle dependencies

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if paused, false otherwise

upgradeTo

Upgrades the contract to a new implementation

Can only be called by accounts with UPGRADER_ROLE

Notes:

  • security: Validates caller has UPGRADER_ROLE

  • validation: Validates newImplementation is not address(0)

  • state-changes: Updates implementation address

  • events: Emits Upgraded event

  • errors: Throws AccessControlUnauthorizedAccount if caller lacks UPGRADER_ROLE

  • reentrancy: Not protected - no external calls

  • access: Restricted to UPGRADER_ROLE

  • oracle: No oracle dependencies

function upgradeTo(address newImplementation) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract

upgradeToAndCall

Upgrades the contract to a new implementation and calls a function

Can only be called by accounts with UPGRADER_ROLE

Notes:

  • security: Validates caller has UPGRADER_ROLE

  • validation: Validates newImplementation is not address(0)

  • state-changes: Updates implementation address and calls initialization

  • events: Emits Upgraded event

  • errors: Throws AccessControlUnauthorizedAccount if caller lacks UPGRADER_ROLE

  • reentrancy: Not protected - no external calls

  • access: Restricted to UPGRADER_ROLE

  • oracle: No oracle dependencies

function upgradeToAndCall(address newImplementation, bytes memory data) external payable;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract
databytesEncoded function call data

GOVERNANCE_ROLE

Returns the governance role identifier

Role that can update vault parameters and governance functions

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query role identifier

  • oracle: No oracle dependencies

function GOVERNANCE_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The governance role bytes32 identifier

EMERGENCY_ROLE

Returns the emergency role identifier

Role that can pause the vault and perform emergency operations

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query role identifier

  • oracle: No oracle dependencies

function EMERGENCY_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The emergency role bytes32 identifier

UPGRADER_ROLE

Returns the upgrader role identifier

Role that can upgrade the contract implementation

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query role identifier

  • oracle: No oracle dependencies

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrader role bytes32 identifier

qeuro

Returns the QEURO token address

The euro-pegged stablecoin token managed by this vault

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query token address

  • oracle: No oracle dependencies

function qeuro() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the QEURO token contract

usdc

Returns the USDC token address

The collateral token used for minting QEURO

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query token address

  • oracle: No oracle dependencies

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the USDC token contract

oracle

Returns the oracle contract address

The price oracle used for EUR/USD conversions

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query oracle address

  • oracle: No oracle dependencies

function oracle() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the oracle contract

mintFee

Returns the current minting fee

Fee charged when minting QEURO with USDC (1e18-scaled, where 1e16 = 1%)

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query minting fee

  • oracle: No oracle dependencies

function mintFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The minting fee as a 1e18-scaled percentage

redemptionFee

Returns the current redemption fee

Fee charged when redeeming QEURO for USDC (1e18-scaled, where 1e16 = 1%)

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query redemption fee

  • oracle: No oracle dependencies

function redemptionFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The redemption fee as a 1e18-scaled percentage

totalUsdcHeld

Returns the total USDC held in the vault

Total amount of USDC collateral backing QEURO

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query total USDC held

  • oracle: No oracle dependencies

function totalUsdcHeld() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total USDC amount (6 decimals)

totalMinted

Returns the total QEURO minted

Total amount of QEURO tokens in circulation

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query total QEURO minted

  • oracle: No oracle dependencies

function totalMinted() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total QEURO amount (18 decimals)

isProtocolCollateralized

Checks if the protocol is properly collateralized by hedgers

Public view function to check collateralization status

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check collateralization status

  • oracle: No oracle dependencies

function isProtocolCollateralized() external view returns (bool isCollateralized, uint256 totalMargin);

Returns

NameTypeDescription
isCollateralizedboolTrue if protocol has active hedging positions
totalMarginuint256Total margin in HedgerPool (0 if not set)

minCollateralizationRatioForMinting

Returns the minimum collateralization ratio for minting

Minimum ratio required for QEURO minting (1e18-scaled percentage format)

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query minimum ratio

  • oracle: No oracle dependencies

function minCollateralizationRatioForMinting() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The minimum collateralization ratio in 1e18-scaled percentage format

userPool

Returns the UserPool contract address

The user pool contract managing user deposits

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query user pool address

  • oracle: No oracle dependencies

function userPool() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the UserPool contract

addHedgerDeposit

Adds hedger USDC deposit to vault's total USDC reserves

Called by HedgerPool when hedgers open positions to unify USDC liquidity

Notes:

  • security: Validates caller is HedgerPool contract and amount is positive

  • validation: Validates amount > 0 and caller is authorized HedgerPool

  • state-changes: Updates totalUsdcHeld with hedger deposit amount

  • events: Emits HedgerDepositAdded with deposit details

  • errors: Throws "Vault: Only HedgerPool can call" if caller is not HedgerPool

  • errors: Throws "Vault: Amount must be positive" if amount is zero

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to HedgerPool contract only

  • oracle: No oracle dependencies

function addHedgerDeposit(uint256 usdcAmount) external;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC deposited by hedger (6 decimals)

withdrawHedgerDeposit

Withdraws hedger USDC deposit from vault's reserves

Called by HedgerPool when hedgers close positions to return their deposits

Notes:

  • security: Validates caller is HedgerPool, amount is positive, and sufficient reserves

  • validation: Validates amount > 0, caller is authorized, and totalUsdcHeld >= amount

  • state-changes: Updates totalUsdcHeld and transfers USDC to hedger

  • events: Emits HedgerDepositWithdrawn with withdrawal details

  • errors: Throws "Vault: Only HedgerPool can call" if caller is not HedgerPool

  • errors: Throws "Vault: Amount must be positive" if amount is zero

  • errors: Throws "Vault: Insufficient USDC reserves" if not enough USDC available

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to HedgerPool contract only

  • oracle: No oracle dependencies

function withdrawHedgerDeposit(address hedger, uint256 usdcAmount) external;

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger receiving the USDC
usdcAmountuint256Amount of USDC to withdraw (6 decimals)

getTotalUsdcAvailable

Gets the total USDC available for hedger deposits

Returns the current total USDC held in the vault for transparency

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public access - anyone can query total USDC held

  • oracle: No oracle dependencies

function getTotalUsdcAvailable() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total USDC held in vault (6 decimals)

updateHedgerPool

Updates the HedgerPool address

Updates the HedgerPool contract address for hedger operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateHedgerPool(address _hedgerPool) external;

Parameters

NameTypeDescription
_hedgerPooladdressNew HedgerPool address

updateUserPool

Updates the UserPool address

Updates the UserPool contract address for user deposit tracking

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateUserPool(address _userPool) external;

Parameters

NameTypeDescription
_userPooladdressNew UserPool address

updateFeeCollector

Updates the fee collector address

Updates the fee collector contract address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateFeeCollector(address _feeCollector) external;

Parameters

NameTypeDescription
_feeCollectoraddressNew fee collector address

updateCollateralizationThresholds

Updates the collateralization thresholds

Updates minimum and critical collateralization ratios

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateCollateralizationThresholds(
    uint256 _minCollateralizationRatioForMinting,
    uint256 _criticalCollateralizationRatio
) external;

Parameters

NameTypeDescription
_minCollateralizationRatioForMintinguint256New minimum collateralization ratio for minting (1e18-scaled percentage)
_criticalCollateralizationRatiouint256New critical collateralization ratio for liquidation (1e18-scaled percentage)

canMint

Checks if minting is allowed based on current collateralization ratio

Returns true if collateralization ratio >= minCollateralizationRatioForMinting

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes - view function

  • events: No events emitted - view function

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check minting status

  • oracle: No oracle dependencies

function canMint() external view returns (bool);

Returns

NameTypeDescription
<none>boolcanMint Whether minting is currently allowed

shouldTriggerLiquidation

Checks if liquidation should be triggered based on the CACHED collateralization ratio

ADVISORY / OBSERVABILITY ONLY. Uses the cached EUR/USD price, which can lag the live oracle price by up to the 2% deviation guard. Mirrors redeemQEURO routing semantics (true only when 0 < CR <= criticalCollateralizationRatio). For an authoritative live check use shouldTriggerLiquidationLive().

Notes:

  • security: View function - no state changes

  • validation: No input validation required - safe view function

  • state-changes: No state changes - view function

  • events: No events emitted - view function

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check liquidation status

  • oracle: Uses cached oracle price

function shouldTriggerLiquidation() external view returns (bool);

Returns

NameTypeDescription
<none>boolshouldLiquidate Whether liquidation should be triggered at the cached price

shouldTriggerLiquidationLive

Authoritative live-price check for whether the protocol is in liquidation territory

Reads the live EUR/USD oracle price and applies the same routing decision as redeemQEURO (0 < CR <= criticalCollateralizationRatio). Non-view because the oracle EUR/USD getter is non-view; call via eth_call/staticCall (no protocol state is mutated).

Notes:

  • security: Read-only intent; performs no protocol state changes

  • validation: Reverts if the oracle EUR/USD price is invalid

  • state-changes: None in this contract

  • events: No events emitted

  • errors: Reverts with InvalidOraclePrice when the oracle price is invalid

  • reentrancy: No protocol state changes; single external oracle read

  • access: Public - anyone can check live liquidation status

  • oracle: Requires a fresh, valid live EUR/USD oracle price

function shouldTriggerLiquidationLive() external returns (bool shouldLiquidate, uint256 collateralizationRatio);

Returns

NameTypeDescription
shouldLiquidateboolTrue if at/below the critical ratio at the live price
collateralizationRatiouint256Current collateralization ratio in 18-decimal percentage format (1e20 = 100%)

getProtocolCollateralizationRatio

Calculates the current protocol collateralization ratio

Returns ratio in 1e18-scaled percentage format (100% = 1e20)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: No state changes - view function

  • events: No events emitted - view function

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check collateralization ratio

  • oracle: Not applicable - no oracle dependency (via HedgerPool)

function getProtocolCollateralizationRatio() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256ratio Current collateralization ratio in 1e18-scaled percentage format

updatePriceCache

Updates the price cache with the current oracle price

Allows governance to manually refresh the price cache

Notes:

  • security: Only callable by governance role

  • validation: Validates oracle price is valid before updating cache

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateBlock, and lastPriceUpdateTime

  • events: Emits PriceCacheUpdated event

  • errors: Reverts if oracle price is invalid

  • reentrancy: Not applicable - no external calls after state changes

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: Requires valid oracle price

function updatePriceCache() external;

initializePriceCache

Initializes the cached EUR/USD price used by view-safe query paths.

Seeds the internal cache with an explicit bootstrap price so view paths have a baseline without performing external oracle reads in this mutating call.

Notes:

  • security: Restricted to governance.

  • validation: Reverts if initialEurUsdPrice is zero.

  • state-changes: Writes the initial cached price and associated timestamp/blocks.

  • events: Emits a price-cache initialization event in the implementation.

  • errors: Reverts when cache is already initialized or input is invalid.

  • reentrancy: Not applicable.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Bootstrap input should come from governance/oracle operations.

function initializePriceCache(uint256 initialEurUsdPrice) external;

Parameters

NameTypeDescription
initialEurUsdPriceuint256Initial EUR/USD price in 18 decimals.

setStakingVault

Configures adapter binding and active status for a vault id.

Governance-managed registry update for external vault routing.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Reverts on invalid vault id or adapter address per implementation rules.

  • state-changes: Updates vault-id adapter and active-status mappings.

  • events: Emits vault configuration event in implementation.

  • errors: Reverts on invalid configuration values.

  • reentrancy: Not typically reentrancy-sensitive.

  • access: Governance-only in implementation.

  • oracle: No oracle dependencies.

function setStakingVault(uint256 vaultId, address adapter, bool active) external;

Parameters

NameTypeDescription
vaultIduint256Vault id to configure.
adapteraddressAdapter contract implementing IExternalStakingVault.
activeboolWhether the vault id should be active for routing.

setDefaultStakingVaultId

Sets the default vault id used for routing/fallback behavior.

vaultId == 0 may be used to clear default routing depending on implementation.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Non-zero ids are validated against active configured adapters.

  • state-changes: Updates default vault-id configuration.

  • events: Emits default-vault update event in implementation.

  • errors: Reverts on invalid/unconfigured ids.

  • reentrancy: Not reentrancy-sensitive.

  • access: Governance-only in implementation.

  • oracle: No oracle dependencies.

function setDefaultStakingVaultId(uint256 vaultId) external;

Parameters

NameTypeDescription
vaultIduint256New default vault id.

setRedemptionPriority

Sets ordered vault ids used for redemption liquidity sourcing.

Replaces current priority ordering with provided array.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Each id is validated as active/configured by implementation.

  • state-changes: Updates redemption-priority configuration.

  • events: Emits redemption-priority update event in implementation.

  • errors: Reverts on invalid ids.

  • reentrancy: Not reentrancy-sensitive.

  • access: Governance-only in implementation.

  • oracle: No oracle dependencies.

function setRedemptionPriority(uint256[] calldata vaultIds) external;

Parameters

NameTypeDescription
vaultIdsuint256[]Ordered vault ids.

deployUsdcToVault

Deploys held USDC into a configured external vault id.

Operator flow for moving idle collateral into yield adapters.

Notes:

  • security: Restricted to operator role in implementation.

  • validation: Reverts on invalid amount, vault config, or insufficient held balance.

  • state-changes: Updates held/external principal accounting and adapter position.

  • events: Emits deployment event in implementation.

  • errors: Reverts on adapter or accounting failures.

  • reentrancy: Implementation is expected to guard with nonReentrant.

  • access: Role-restricted in implementation.

  • oracle: No oracle dependencies.

function deployUsdcToVault(uint256 vaultId, uint256 usdcAmount) external;

Parameters

NameTypeDescription
vaultIduint256Target vault id.
usdcAmountuint256Amount of USDC to deploy.

selfRegisterStQEURO

Registers this vault into stQEUROFactory and deploys its dedicated token.

Binds the vault to a deterministic stQEURO token address and records factory linkage.

Notes:

  • security: Intended for governance-only execution in implementation.

  • validation: Implementations must validate factory address, vault id, and registration uniqueness.

  • state-changes: Updates factory/token/vault-id bindings on successful registration.

  • events: Emits registration event in implementation.

  • errors: Reverts for invalid input, duplicate initialization, or registration mismatch.

  • reentrancy: Implementation protects external registration flow with reentrancy guard.

  • access: Access controlled by implementation (governance role).

  • oracle: No oracle dependencies.

function selfRegisterStQEURO(address factory, uint256 vaultId, string calldata vaultName)
    external
    returns (address token);

Parameters

NameTypeDescription
factoryaddressAddress of stQEUROFactory.
vaultIduint256Target vault id.
vaultNamestringUppercase alphanumeric vault name.

Returns

NameTypeDescription
tokenaddressNewly deployed stQEURO token address.

updateHedgerRewardFeeSplit

Updates the protocol‑fee share routed to HedgerPool reward reserve.

Sets the fraction of protocol fees (scaled by 1e18 where 1e18 = 100%) that is forwarded to HedgerPool’s reward reserve instead of remaining in the vault.

Notes:

  • security: Only callable by governance; misconfiguration can starve protocol or hedgers.

  • validation: Implementation validates that newSplit is within acceptable bounds.

  • state-changes: Updates internal accounting for how fees are split on collection.

  • events: Emits an event in the implementation describing the new split.

  • errors: Reverts on invalid split values as defined by implementation.

  • reentrancy: Not applicable – configuration only, no external transfers.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No direct oracle dependency.

function updateHedgerRewardFeeSplit(uint256 newSplit) external;

Parameters

NameTypeDescription
newSplituint256New fee‑share value (1e18‑scaled, 0–1e18 allowed by implementation).

getVaultExposure

Returns exposure snapshot for a vault id.

Includes adapter address, active status, tracked principal, and current underlying read.

Notes:

  • security: Read-only helper.

  • validation: No additional validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No explicit errors expected by interface contract.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultExposure(uint256 vaultId)
    external
    view
    returns (address adapter, bool active, uint256 principalTracked, uint256 currentUnderlying);

Parameters

NameTypeDescription
vaultIduint256Vault id to query.

Returns

NameTypeDescription
adapteraddressAdapter address bound to vault id.
activeboolWhether the vault id is active.
principalTrackeduint256Principal tracked locally for vault id.
currentUnderlyinguint256Current underlying balance from adapter (implementation may fallback).

defaultStakingVaultId

Returns configured default staking vault id.

Used by clients to infer default mint routing.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function defaultStakingVaultId() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Default vault id (0 when unset).

totalUsdcInExternalVaults

Returns total principal tracked across external vault adapters.

Aggregated accounting metric for externally deployed USDC.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function totalUsdcInExternalVaults() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total USDC principal tracked in external vaults.

stQEUROFactory

Returns configured stQEUROFactory address.

Read-only accessor for the factory bound to this vault instance.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function stQEUROFactory() external view returns (address);

stQEUROTokenByVaultId

Returns stQEURO token address bound to a vault id.

Mapping accessor for vault-id-to-stQEURO token identity.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required; unknown ids return zero address.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function stQEUROTokenByVaultId(uint256 vaultId) external view returns (address);

Parameters

NameTypeDescription
vaultIduint256Vault identifier.

Returns

NameTypeDescription
<none>addressstQEURO token address bound to vaultId (or zero if unset).

VAULT_OPERATOR_ROLE

Returns the vault operator role identifier

Role that can trigger Aave deployments (assigned to UserPool)

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query role identifier

  • oracle: No oracle dependencies

function VAULT_OPERATOR_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The vault operator role bytes32 identifier

ISecureUpgradeable

Git Source

Title: ISecureUpgradeable

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the SecureUpgradeable base contract

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the secure upgradeable contract

Sets up the secure upgradeable with initial configuration and assigns roles to admin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin) external;

Parameters

NameTypeDescription
adminaddressAddress that receives admin roles

setTimelock

Set the timelock contract

Configures the timelock contract for secure upgrade management

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function setTimelock(address _timelock) external;

Parameters

NameTypeDescription
_timelockaddressAddress of the timelock contract

toggleSecureUpgrades

Toggle secure upgrades

Enables or disables the secure upgrade mechanism

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function toggleSecureUpgrades(bool enabled) external;

Parameters

NameTypeDescription
enabledboolWhether to enable secure upgrades

proposeUpgrade

Propose an upgrade through the timelock

Initiates a secure upgrade proposal with timelock delay

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function proposeUpgrade(address newImplementation, string calldata description, uint256 customDelay) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the upgrade
customDelayuint256Optional custom delay

executeUpgrade

Execute an upgrade through the timelock

Executes a previously proposed upgrade after timelock delay

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function executeUpgrade(address newImplementation) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

emergencyUpgrade

Emergency upgrade (bypasses timelock, requires emergency mode)

Performs immediate upgrade in emergency situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyUpgrade(address newImplementation, string calldata description) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the emergency upgrade

isUpgradePending

Check if an upgrade is pending

Checks if there's a pending upgrade for the given implementation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isUpgradePending(address implementation) external view returns (bool isPending);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
isPendingboolWhether the upgrade is pending

getPendingUpgrade

Get pending upgrade details

Returns detailed information about a pending upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPendingUpgrade(address implementation)
    external
    view
    returns (ITimelockUpgradeable.PendingUpgrade memory upgrade);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
upgradeITimelockUpgradeable.PendingUpgradePending upgrade details

canExecuteUpgrade

Check if an upgrade can be executed

Checks if the timelock delay has passed and upgrade can be executed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function canExecuteUpgrade(address implementation) external view returns (bool canExecute);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
canExecuteboolWhether the upgrade can be executed

getUpgradeSecurityStatus

Get upgrade security status

Returns current security configuration for upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getUpgradeSecurityStatus()
    external
    view
    returns (address timelockAddress, bool secureUpgradesEnabled_, bool hasTimelock);

Returns

NameTypeDescription
timelockAddressaddressAddress of the timelock contract
secureUpgradesEnabled_boolWhether secure upgrades are enabled
hasTimelockboolWhether timelock is set

proposeEmergencyDisableSecureUpgrades

Propose emergency disable of secure upgrades (starts 24‑hour delay window).

Increments the emergency‑disable proposal id, resets approvals and sets a future timestamp after which the proposal can be applied.

Notes:

  • security: Only callable by an authorized admin role in implementations.

  • validation: Reverts if secure upgrades are already disabled.

  • state-changes: Bumps proposal id, clears approval count and sets emergencyDisablePendingAt.

  • events: Emits an event describing the newly created proposal and activation time.

  • errors: Reverts with a protocol‑specific error if secure upgrades are not active.

  • reentrancy: Not applicable – implementations should avoid external calls.

  • access: Restricted to governance/admin roles.

  • oracle: No oracle dependencies.

function proposeEmergencyDisableSecureUpgrades() external;

approveEmergencyDisableSecureUpgrades

Register an admin approval for the currently pending emergency‑disable proposal.

Records that the caller has approved the latest proposal and increases the approval count, enforcing one‑approval‑per‑admin semantics.

Notes:

  • security: Only callable by an authorized admin role in implementations.

  • validation: Reverts if there is no active proposal or caller already approved.

  • state-changes: Marks the caller as having approved and increments approval count.

  • events: Emits an event with updated approval count.

  • errors: Reverts with protocol‑specific errors on missing proposal or duplicate approval.

  • reentrancy: Not applicable – implementations should avoid external calls.

  • access: Restricted to governance/admin roles.

  • oracle: No oracle dependencies.

function approveEmergencyDisableSecureUpgrades() external;

applyEmergencyDisableSecureUpgrades

Apply pending emergency‑disable once quorum and delay are satisfied.

Disables secure upgrades permanently for the implementation once:

  • the activation timestamp is reached, and
  • the approval count is at least the quorum.

Notes:

  • security: Only callable by an authorized admin role; enforces timelock and quorum.

  • validation: Reverts on mismatched expectedProposalId, missing quorum or no pending proposal.

  • state-changes: Clears pending state and sets secureUpgradesEnabled to false.

  • events: Emits an event indicating secure upgrades have been disabled.

  • errors: Reverts with protocol‑specific errors on invalid state or insufficient approvals.

  • reentrancy: Not applicable – implementations should avoid external calls after state changes.

  • access: Restricted to governance/admin roles.

  • oracle: No oracle dependencies.

function applyEmergencyDisableSecureUpgrades(uint256 expectedProposalId) external;

Parameters

NameTypeDescription
expectedProposalIduint256Proposal id expected by caller (replay/mismatch protection).

enableSecureUpgrades

Enable secure upgrades after emergency

Re-enables secure upgrade mechanism after emergency

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function enableSecureUpgrades() external;

emergencyDisablePendingAt

Timestamp when emergency disable can be applied for the current proposal.

Returns 0 when there is no active proposal.

Notes:

  • security: View helper; no access restriction.

  • validation: None.

  • state-changes: None – view function only.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public.

  • oracle: No oracle dependencies.

function emergencyDisablePendingAt() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256pendingAt Unix timestamp after which applyEmergencyDisableSecureUpgrades is allowed.

emergencyDisableProposalId

Returns the current emergency‑disable proposal id.

Value is 0 when no proposal has ever been created.

Notes:

  • security: View helper; no access restriction.

  • validation: None.

  • state-changes: None – view function only.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public.

  • oracle: No oracle dependencies.

function emergencyDisableProposalId() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256proposalId Identifier of the latest emergency‑disable proposal.

emergencyDisableApprovalCount

Returns the current number of admin approvals for the active proposal.

Counts how many distinct admin addresses have approved the latest proposal id.

Notes:

  • security: View helper; no access restriction.

  • validation: None.

  • state-changes: None – view function only.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public.

  • oracle: No oracle dependencies.

function emergencyDisableApprovalCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256approvalCount Number of recorded approvals.

emergencyDisableQuorum

Returns the number of approvals required to apply emergency disable.

Exposes the implementation’s quorum constant for off‑chain monitoring.

Notes:

  • security: View helper; no access restriction.

  • validation: None.

  • state-changes: None – view function only.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public.

  • oracle: No oracle dependencies.

function emergencyDisableQuorum() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256quorum Number of admin approvals required to execute emergency disable.

hasEmergencyDisableApproval

Returns whether a given approver address approved a specific proposal id.

MUST return false when approver is the zero address or proposalId is zero.

Notes:

  • security: View helper; no access restriction.

  • validation: Treats invalid inputs as “not approved”.

  • state-changes: None – view function only.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable – view function.

  • access: Public.

  • oracle: No oracle dependencies.

function hasEmergencyDisableApproval(uint256 proposalId, address approver) external view returns (bool);

Parameters

NameTypeDescription
proposalIduint256Proposal identifier to check.
approveraddressAddress of the admin whose approval status is queried.

Returns

NameTypeDescription
<none>boolhasApproved True if approver has approved proposalId.

timelock

Returns the timelock contract address

Returns the ITimelockUpgradeable contract instance

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function timelock() external view returns (ITimelockUpgradeable);

Returns

NameTypeDescription
<none>ITimelockUpgradeableThe timelock contract

secureUpgradesEnabled

Returns whether secure upgrades are enabled

Indicates if the secure upgrade mechanism is active

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function secureUpgradesEnabled() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if secure upgrades are enabled

UPGRADER_ROLE

Returns the upgrader role identifier

Role that can perform upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrader role bytes32 identifier

hasRole

Checks if an account has a specific role

Returns true if the account has been granted the role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasRole(bytes32 role, address account) external view returns (bool);

Parameters

NameTypeDescription
rolebytes32The role to check
accountaddressThe account to check

Returns

NameTypeDescription
<none>boolTrue if the account has the role

getRoleAdmin

Gets the admin role for a given role

Returns the role that is the admin of the given role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getRoleAdmin(bytes32 role) external view returns (bytes32);

Parameters

NameTypeDescription
rolebytes32The role to get admin for

Returns

NameTypeDescription
<none>bytes32The admin role

grantRole

Grants a role to an account

Can only be called by an account with the admin role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function grantRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to grant
accountaddressThe account to grant the role to

revokeRole

Revokes a role from an account

Can only be called by an account with the admin role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function revokeRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to revoke
accountaddressThe account to revoke the role from

renounceRole

Renounces a role from the caller

The caller gives up their own role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function renounceRole(bytes32 role, address callerConfirmation) external;

Parameters

NameTypeDescription
rolebytes32The role to renounce
callerConfirmationaddressConfirmation that the caller is renouncing their own role

upgradeTo

Upgrades the contract to a new implementation

Can only be called by accounts with UPGRADER_ROLE

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeTo(address newImplementation) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract

upgradeToAndCall

Upgrades the contract to a new implementation and calls a function

Can only be called by accounts with UPGRADER_ROLE

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeToAndCall(address newImplementation, bytes memory data) external payable;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract
databytesEncoded function call data

ISlippageStorage

Git Source

Title: ISlippageStorage

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the Quantillon SlippageStorage contract

Stores on-chain slippage data published by an off-chain service. Provides rate-limited writes via WRITER_ROLE and config management via MANAGER_ROLE.

Note: security-contact: team@quantillon.money

Functions

initialize

Initialize the SlippageStorage contract

Sets up roles, rate-limit parameters, and treasury. Admin receives DEFAULT_ADMIN_ROLE, MANAGER_ROLE, EMERGENCY_ROLE, and UPGRADER_ROLE. Writer receives WRITER_ROLE. Callable only once via proxy deployment.

Notes:

  • security: Validates admin, writer, and treasury are non-zero; enforces config bounds

  • validation: Validates admin/writer/treasury != address(0); interval and threshold within max

  • state-changes: Grants roles, sets minUpdateInterval, deviationThresholdBps, treasury

  • events: No events emitted

  • errors: Reverts with ZeroAddress if admin/writer/treasury is zero; reverts with ConfigValueTooHigh if interval or threshold exceeds max

  • reentrancy: Protected by initializer modifier (callable only once)

  • access: Public - only callable once during proxy deployment

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address writer,
    uint48 minInterval,
    uint16 deviationThreshold,
    address treasury,
    uint8 initialEnabledSources
) external;

Parameters

NameTypeDescription
adminaddressAddress receiving DEFAULT_ADMIN_ROLE and all management roles
writeraddressAddress receiving WRITER_ROLE (the off-chain publisher service wallet)
minIntervaluint48Minimum seconds between successive writes (0..MAX_UPDATE_INTERVAL)
deviationThresholduint16Deviation in bps that bypasses rate limit (0..MAX_DEVIATION_THRESHOLD)
treasuryaddressTreasury address for token/ETH recovery
initialEnabledSourcesuint8Bitmask of initially enabled sources (0x01=Lighter, 0x02=Hyperliquid, 0x03=both)

updateSlippage

Publish a new slippage snapshot on-chain

Rate-limited: if within minUpdateInterval since last update, only allows the write when |newWorstCaseBps - lastWorstCaseBps| > deviationThresholdBps. First update always succeeds (timestamp == 0 means no prior data).

Notes:

  • security: Requires WRITER_ROLE; blocked when paused; rate-limited by minUpdateInterval

  • validation: Checks elapsed time since last update; validates deviation if within interval

  • state-changes: Overwrites _snapshot with new values, timestamp, and block number

  • events: Emits SlippageUpdated(midPrice, worstCaseBps, spreadBps, depthEur, timestamp)

  • errors: Reverts with RateLimitTooHigh if within interval and deviation is below threshold

  • reentrancy: Not protected - no external calls made during execution

  • access: Restricted to WRITER_ROLE; blocked when contract is paused

  • oracle: No on-chain oracle dependency; data is pushed by the off-chain Slippage Monitor

function updateSlippage(
    uint128 midPrice,
    uint128 depthEur,
    uint16 worstCaseBps,
    uint16 spreadBps,
    uint16[5] calldata bucketBps
) external;

Parameters

NameTypeDescription
midPriceuint128EUR/USD mid price (18 decimals)
depthEuruint128Total ask depth in EUR (18 decimals)
worstCaseBpsuint16Worst-case slippage across buckets (bps)
spreadBpsuint16Bid-ask spread (bps)
bucketBpsuint16[5]Per-size slippage in bps, fixed order: [10k, 50k, 100k, 250k, 1M]

updateSlippageBatch

Publish slippage snapshots for multiple sources in a single transaction

Sources disabled in enabledSources bitmask are silently skipped (not reverted). Rate-limited per source: within-interval updates are skipped unless deviation > threshold. Lighter source (sourceId=0) writes to the legacy _snapshot slot for backward compat.

Notes:

  • security: Requires WRITER_ROLE; blocked when paused

  • validation: Per-source rate limit: skips (does not revert) if within interval and deviation <= threshold

  • state-changes: Writes each enabled source's snapshot; Lighter updates _snapshot for backward compat

  • events: Emits SlippageSourceUpdated for each source actually written

  • errors: No explicit reverts for rate-limited sources (silently skipped)

  • reentrancy: Not protected - no external calls made during execution

  • oracle: No on-chain oracle dependency; data is pushed by the off-chain Slippage Monitor

  • access: Restricted to WRITER_ROLE; blocked when contract is paused

function updateSlippageBatch(SourceUpdate[] calldata updates) external;

Parameters

NameTypeDescription
updatesSourceUpdate[]Array of per-source snapshot inputs

setMinUpdateInterval

Update the minimum interval between successive slippage writes

Setting to 0 disables the rate limit; MAX_UPDATE_INTERVAL caps at 1 hour.

Notes:

  • security: Requires MANAGER_ROLE; enforces upper bound MAX_UPDATE_INTERVAL

  • validation: Validates newInterval <= MAX_UPDATE_INTERVAL

  • state-changes: Updates minUpdateInterval state variable

  • events: Emits ConfigUpdated("minUpdateInterval", oldValue, newValue)

  • errors: Reverts with ConfigValueTooHigh if newInterval > MAX_UPDATE_INTERVAL

  • reentrancy: Not protected - no external calls made

  • access: Restricted to MANAGER_ROLE

  • oracle: No oracle dependencies

function setMinUpdateInterval(uint48 newInterval) external;

Parameters

NameTypeDescription
newIntervaluint48New minimum interval in seconds (0..MAX_UPDATE_INTERVAL)

setDeviationThreshold

Update the worst-case bps deviation threshold that bypasses the rate limit

When |newWorstCaseBps - lastWorstCaseBps| > threshold, rate limit is bypassed.

Notes:

  • security: Requires MANAGER_ROLE; enforces upper bound MAX_DEVIATION_THRESHOLD (500 bps)

  • validation: Validates newThreshold <= MAX_DEVIATION_THRESHOLD

  • state-changes: Updates deviationThresholdBps state variable

  • events: Emits ConfigUpdated("deviationThresholdBps", oldValue, newValue)

  • errors: Reverts with ConfigValueTooHigh if newThreshold > MAX_DEVIATION_THRESHOLD

  • reentrancy: Not protected - no external calls made

  • access: Restricted to MANAGER_ROLE

  • oracle: No oracle dependencies

function setDeviationThreshold(uint16 newThreshold) external;

Parameters

NameTypeDescription
newThresholduint16New deviation threshold in bps (0..MAX_DEVIATION_THRESHOLD)

pause

Pause the contract, blocking all slippage updates

Once paused, updateSlippage reverts until unpaused.

Notes:

  • security: Requires EMERGENCY_ROLE; prevents unauthorized pausing

  • validation: No input validation required

  • state-changes: Sets OpenZeppelin Pausable internal paused flag to true

  • events: Emits Paused(account) from OpenZeppelin PausableUpgradeable

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls made

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function pause() external;

unpause

Unpause the contract, resuming slippage updates

Restores normal operation; WRITER_ROLE can immediately publish again.

Notes:

  • security: Requires EMERGENCY_ROLE; prevents unauthorized unpausing

  • validation: No input validation required

  • state-changes: Sets OpenZeppelin Pausable internal paused flag to false

  • events: Emits Unpaused(account) from OpenZeppelin PausableUpgradeable

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls made

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function unpause() external;

getSlippage

Get the full current slippage snapshot

Returns a zero-valued struct if updateSlippage has never been called.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored state only

function getSlippage() external view returns (SlippageSnapshot memory snapshot);

Returns

NameTypeDescription
snapshotSlippageSnapshotThe latest SlippageSnapshot stored on-chain

getBucketBps

Get per-bucket slippage in bps in canonical size order

Returns buckets in fixed order: [10k EUR, 50k EUR, 100k EUR, 250k EUR, 1M EUR]. All values are zero if updateSlippage has never been called.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored state only

function getBucketBps() external view returns (uint16[5] memory bucketBps);

Returns

NameTypeDescription
bucketBpsuint16[5]Array of 5 slippage values in bps for each order size bucket

getSlippageAge

Get seconds elapsed since the last on-chain slippage update

Returns 0 if no update has ever been published (timestamp == 0).

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored timestamp only

function getSlippageAge() external view returns (uint256 age);

Returns

NameTypeDescription
ageuint256Seconds since last updateSlippage call, or 0 if never updated

getSlippageBySource

Get the full slippage snapshot for a specific source

sourceId=0 (SOURCE_LIGHTER) reads from the legacy _snapshot slot. Other sourceIds read from _sourceSnapshots mapping. Returns a zero-valued struct if no data has been published for that source.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • oracle: No oracle dependencies - reads stored state only

  • access: Public - no restrictions

function getSlippageBySource(uint8 sourceId) external view returns (SlippageSnapshot memory snapshot);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_LIGHTER=0, SOURCE_HYPERLIQUID=1)

Returns

NameTypeDescription
snapshotSlippageSnapshotThe latest SlippageSnapshot for the given source

getSlippageAgeBySource

Get seconds elapsed since the last on-chain update for a specific source

Returns 0 if no update has ever been published for the source (timestamp == 0).

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • oracle: No oracle dependencies - reads stored timestamp only

  • access: Public - no restrictions

function getSlippageAgeBySource(uint8 sourceId) external view returns (uint256 age);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_LIGHTER=0, SOURCE_HYPERLIQUID=1)

Returns

NameTypeDescription
ageuint256Seconds since last update for that source, or 0 if never updated

enabledSources

Get the bitmask of enabled sources (bit N = source N enabled)

Bit 0 = SOURCE_LIGHTER, Bit 1 = SOURCE_HYPERLIQUID. 0x03 = both enabled.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • oracle: No oracle dependencies

  • access: Public - no restrictions

function enabledSources() external view returns (uint8 mask);

Returns

NameTypeDescription
maskuint8Current enabled sources bitmask

setEnabledSources

Update which sources are enabled for storage in updateSlippageBatch

Bit 0 = SOURCE_LIGHTER, Bit 1 = SOURCE_HYPERLIQUID. 0x03 = both enabled. Disabled sources are silently skipped in batch writes without reverting.

Notes:

  • security: Requires MANAGER_ROLE

  • validation: No additional validation; all uint8 values accepted

  • state-changes: Updates enabledSources state variable

  • events: Emits EnabledSourcesUpdated(oldMask, newMask)

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls made

  • oracle: No oracle dependencies

  • access: Restricted to MANAGER_ROLE

function setEnabledSources(uint8 mask) external;

Parameters

NameTypeDescription
maskuint8New bitmask (0x01=Lighter only, 0x02=Hyperliquid only, 0x03=both)

minUpdateInterval

Get the current minimum update interval

Rate limit applied to consecutive updateSlippage calls.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies

function minUpdateInterval() external view returns (uint48 interval);

Returns

NameTypeDescription
intervaluint48Minimum seconds required between successive writes

deviationThresholdBps

Get the current deviation threshold that bypasses the rate limit

When |newWorstCaseBps - lastWorstCaseBps| exceeds this, rate limit is bypassed.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies

function deviationThresholdBps() external view returns (uint16 threshold);

Returns

NameTypeDescription
thresholduint16Current deviation threshold in bps

recoverToken

Recover ERC20 tokens accidentally sent to this contract

Transfers the specified amount to the treasury address.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE; prevents unauthorized token withdrawals

  • validation: Implicitly validated via SafeERC20 transfer

  • state-changes: No internal state changes; transfers token balance externally

  • events: No events emitted from this contract

  • errors: Reverts if ERC20 transfer fails (SafeERC20 revert)

  • reentrancy: Not protected - external ERC20 call; admin-only mitigates risk

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressERC20 token contract address to recover
amountuint256Amount of tokens to transfer to treasury (token decimals)

recoverETH

Recover ETH accidentally sent to this contract

Transfers the entire ETH balance to the treasury address.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE; prevents unauthorized ETH withdrawals

  • validation: No input validation required; uses address(this).balance

  • state-changes: No internal state changes; transfers ETH balance externally

  • events: Emits ETHRecovered(treasury, amount)

  • errors: Reverts if ETH transfer fails

  • reentrancy: Not protected - external ETH transfer; admin-only mitigates risk

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverETH() external;

Events

SlippageUpdated

Emitted when slippage data is updated on-chain (Lighter legacy single-source path)

event SlippageUpdated(uint128 midPrice, uint16 worstCaseBps, uint16 spreadBps, uint128 depthEur, uint48 timestamp);

SlippageSourceUpdated

Emitted once per source written in updateSlippageBatch

event SlippageSourceUpdated(
    uint8 indexed sourceId,
    uint128 midPrice,
    uint16 worstCaseBps,
    uint16 spreadBps,
    uint128 depthEur,
    uint48 timestamp
);

EnabledSourcesUpdated

Emitted when the enabledSources bitmask is changed by MANAGER_ROLE

event EnabledSourcesUpdated(uint8 oldMask, uint8 newMask);

ConfigUpdated

Emitted when a config parameter is changed

event ConfigUpdated(string indexed param, uint256 oldValue, uint256 newValue);

TreasuryUpdated

Emitted when treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

Structs

SourceUpdate

Input for one source in a batch update

struct SourceUpdate {
    uint8 sourceId; // SOURCE_LIGHTER=0, SOURCE_HYPERLIQUID=1
    uint128 midPrice; // EUR/USD mid price (18 decimals)
    uint128 depthEur; // Total ask depth in EUR (18 decimals)
    uint16 worstCaseBps;
    uint16 spreadBps;
    uint16[5] bucketBps; // [10k, 50k, 100k, 250k, 1M]
}

SlippageSnapshot

Packed on-chain slippage snapshot (2 storage slots)

Storage layout (must not be reordered — UUPS upgrade-safe): Slot 0 (32 bytes): midPrice (uint128) + depthEur (uint128) Slot 1 (26/32 bytes): worstCaseBps (2) + spreadBps (2) + timestamp (6) + blockNumber (6) + bps10k (2) + bps50k (2) + bps100k (2) + bps250k (2) + bps1M (2) Individual uint16 fields are used instead of uint16[5] because Solidity arrays always start a new storage slot, which would waste a full slot.

struct SlippageSnapshot {
    uint128 midPrice; // EUR/USD mid price (18 decimals)
    uint128 depthEur; // Total ask depth in EUR (18 decimals)
    uint16 worstCaseBps; // Worst-case slippage across buckets (bps)
    uint16 spreadBps; // Bid-ask spread (bps)
    uint48 timestamp; // Block timestamp of update
    uint48 blockNumber; // Block number of update
    uint16 bps10k; // Slippage bps for 10k EUR bucket
    uint16 bps50k; // Slippage bps for 50k EUR bucket
    uint16 bps100k; // Slippage bps for 100k EUR bucket
    uint16 bps250k; // Slippage bps for 250k EUR bucket
    uint16 bps1M; // Slippage bps for 1M EUR bucket
}

IStQEUROFactory

Git Source

Functions

registerVault

Registers caller vault and deploys a dedicated stQEURO proxy.

Implementation enforces vault uniqueness and deterministic token deployment.

Notes:

  • security: Restricted by implementation access control.

  • validation: Implementations should validate vault id/name and uniqueness.

  • state-changes: Updates factory registry mappings and deploys token proxy.

  • events: Emits registration event in implementation.

  • errors: Reverts on invalid input or duplicate registration.

  • reentrancy: Implementation should use CEI-safe ordering for external deployment call.

  • access: Access controlled by implementation.

  • oracle: No oracle dependencies.

function registerVault(uint256 vaultId, string calldata vaultName) external returns (address stQEUROToken);

Parameters

NameTypeDescription
vaultIduint256Vault identifier to register.
vaultNamestringUppercase alphanumeric vault name.

Returns

NameTypeDescription
stQEUROTokenaddressRegistered stQEURO token address.

previewVaultToken

Previews deterministic stQEURO address for a vault registration tuple.

Read-only helper used before registration to bind expected token address.

Notes:

  • security: Read-only helper.

  • validation: Implementations should validate vault inputs and name format.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts on invalid preview inputs.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function previewVaultToken(address vault, uint256 vaultId, string calldata vaultName)
    external
    view
    returns (address stQEUROToken);

Parameters

NameTypeDescription
vaultaddressVault address that will register.
vaultIduint256Vault identifier to register.
vaultNamestringUppercase alphanumeric vault name.

Returns

NameTypeDescription
stQEUROTokenaddressPredicted token address for registration tuple.

getStQEUROByVaultId

Returns registered stQEURO token by vault id.

Read-only registry lookup.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getStQEUROByVaultId(uint256 vaultId) external view returns (address stQEUROToken);

Parameters

NameTypeDescription
vaultIduint256Vault identifier.

Returns

NameTypeDescription
stQEUROTokenaddressRegistered token address (or zero if unset).

getVaultIdsByVault

Returns all vault ids registered by a given vault contract.

A single QuantillonVault can register multiple staking vault ids.

Notes:

  • security: Read-only registry accessor.

  • validation: No additional validation; unknown vaults return an empty array.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultIdsByVault(address vault) external view returns (uint256[] memory vaultIds);

Parameters

NameTypeDescription
vaultaddressVault contract address.

Returns

NameTypeDescription
vaultIdsuint256[]Array of registered vault ids for that vault contract.

getVaultById

Returns vault address mapped to a vault id.

Read-only registry lookup.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultById(uint256 vaultId) external view returns (address vault);

Parameters

NameTypeDescription
vaultIduint256Vault identifier.

Returns

NameTypeDescription
vaultaddressVault address (or zero if unset).

getVaultIdByStQEURO

Returns vault id mapped to an stQEURO token address.

Read-only reverse-registry lookup.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultIdByStQEURO(address stQEUROToken) external view returns (uint256 vaultId);

Parameters

NameTypeDescription
stQEUROTokenaddressRegistered token address.

Returns

NameTypeDescription
vaultIduint256Vault identifier (or zero if unset).

getVaultName

Returns canonical vault name string for a vault id.

Read-only registry lookup.

Notes:

  • security: Read-only accessor.

  • validation: No input validation required.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No errors expected.

  • reentrancy: Not applicable for view function.

  • access: Public view.

  • oracle: No oracle dependencies.

function getVaultName(uint256 vaultId) external view returns (string memory vaultName);

Parameters

NameTypeDescription
vaultIduint256Vault identifier.

Returns

NameTypeDescription
vaultNamestringRegistered vault name string.

IStorkOracle

Git Source

Inherits: IOracle

Title: IStorkOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the Quantillon Stork-based oracle

Extends IOracle with Stork-specific functions This interface is specific to StorkOracle implementation

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the oracle with admin and Stork feed addresses

Sets up the oracle with initial configuration and assigns roles to admin

Notes:

  • security: Validates all addresses are non-zero, grants admin roles

  • validation: Validates all input addresses are not address(0)

  • state-changes: Initializes all state variables, sets default price bounds

  • events: Emits PriceUpdated during initial price update

  • errors: Throws "Oracle: Admin cannot be zero" if admin is address(0)

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during deployment

  • oracle: Initializes Stork price feed interfaces

function initialize(
    address admin,
    address _storkFeedAddress,
    bytes32 _eurUsdFeedId,
    bytes32 _usdcUsdFeedId,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and manager roles
_storkFeedAddressaddressStork feed contract address
_eurUsdFeedIdbytes32Stork EUR/USD feed ID (bytes32)
_usdcUsdFeedIdbytes32Stork USDC/USD feed ID (bytes32)
_treasuryaddressTreasury address

updatePriceBounds

Updates EUR/USD min and max acceptable prices

Updates the price bounds for EUR/USD validation with security checks

Notes:

  • security: Validates min < max and reasonable bounds

  • validation: Validates price bounds are within acceptable range

  • state-changes: Updates minPrice and maxPrice state variables

  • events: Emits PriceBoundsUpdated event

  • errors: Throws if minPrice >= maxPrice or invalid bounds

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency - configuration update only

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external;

Parameters

NameTypeDescription
_minPriceuint256New minimum price (18 decimals)
_maxPriceuint256New maximum price (18 decimals)

updateUsdcTolerance

Updates the allowed USDC deviation from $1.00 in basis points

Updates the USDC price tolerance for validation with security checks

Notes:

  • security: Validates tolerance is within reasonable limits

  • validation: Validates tolerance is not zero and within max bounds

  • state-changes: Updates usdcTolerance state variable

  • events: Emits UsdcToleranceUpdated event

  • errors: Throws if tolerance is invalid or out of bounds

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency - configuration update only

function updateUsdcTolerance(uint256 newToleranceBps) external;

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance (e.g., 200 = 2%)

updatePriceFeeds

Updates Stork feed addresses and feed IDs

Updates the addresses and feed IDs of both Stork price feeds with validation

Notes:

  • security: Validates feed address is non-zero and contract exists

  • validation: Validates all addresses are not address(0)

  • state-changes: Updates eurUsdPriceFeed, usdcUsdPriceFeed, and feed IDs

  • events: Emits PriceFeedsUpdated event

  • errors: Throws if feed address is zero or invalid

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates Stork feed contract references

function updatePriceFeeds(address _storkFeedAddress, bytes32 _eurUsdFeedId, bytes32 _usdcUsdFeedId) external;

Parameters

NameTypeDescription
_storkFeedAddressaddressNew Stork feed contract address
_eurUsdFeedIdbytes32New EUR/USD feed ID
_usdcUsdFeedIdbytes32New USDC/USD feed ID

resetCircuitBreaker

Clears circuit breaker and attempts to resume live prices

Resets the circuit breaker state to allow normal price operations

Notes:

  • security: Resets circuit breaker after manual intervention

  • validation: Validates circuit breaker was previously triggered

  • state-changes: Resets circuitBreakerTriggered flag

  • events: Emits CircuitBreakerReset event

  • errors: No errors thrown

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Resumes normal oracle price queries

function resetCircuitBreaker() external;

triggerCircuitBreaker

Manually triggers circuit breaker to use fallback prices

Activates circuit breaker to switch to fallback price mode for safety

Notes:

  • security: Manually activates circuit breaker for emergency situations

  • validation: No validation - emergency function

  • state-changes: Sets circuitBreakerTriggered flag to true

  • events: Emits CircuitBreakerTriggered event

  • errors: No errors thrown

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Switches to fallback prices instead of live oracle queries

function triggerCircuitBreaker() external;

pause

Pauses all oracle operations

Pauses the oracle contract to halt all price operations

Notes:

  • security: Emergency pause to halt all oracle operations

  • validation: No validation - emergency function

  • state-changes: Sets paused state to true

  • events: Emits Paused event

  • errors: No errors thrown

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Halts all oracle price queries

function pause() external;

unpause

Unpauses oracle operations

Resumes oracle operations after being paused

Notes:

  • security: Resumes oracle operations after pause

  • validation: Validates contract was previously paused

  • state-changes: Sets paused state to false

  • events: Emits Unpaused event

  • errors: No errors thrown

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Resumes normal oracle price queries

function unpause() external;

recoverToken

Recovers ERC20 tokens sent to the oracle contract by mistake

Allows recovery of ERC20 tokens accidentally sent to the oracle contract

Notes:

  • security: Transfers tokens to treasury, prevents accidental loss

  • validation: Validates token and amount are non-zero

  • state-changes: Transfers tokens from contract to treasury

  • events: Emits TokenRecovered event

  • errors: Throws if token is zero address or transfer fails

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to transfer

recoverETH

Recovers ETH sent to the oracle contract by mistake

Allows recovery of ETH accidentally sent to the oracle contract

Notes:

  • security: Transfers ETH to treasury, prevents accidental loss

  • validation: Validates contract has ETH balance

  • state-changes: Transfers ETH from contract to treasury

  • events: Emits ETHRecovered event

  • errors: Throws if transfer fails

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverETH() external;

ITimelockUpgradeable

Git Source

Title: ITimelockUpgradeable

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the secure upgrade mechanism with timelock and multi-sig requirements

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the timelock upgradeable contract

Sets up the timelock with initial configuration and assigns roles to admin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin) external;

Parameters

NameTypeDescription
adminaddressAddress that receives admin and upgrade proposer roles

proposeUpgrade

Propose an upgrade with timelock

Initiates a secure upgrade proposal with timelock delay and multi-sig requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function proposeUpgrade(address newImplementation, string calldata description, uint256 customDelay) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the upgrade
customDelayuint256Optional custom delay (must be >= UPGRADE_DELAY)

approveUpgrade

Approve a pending upgrade (multi-sig signer only)

Allows multi-sig signers to approve pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function approveUpgrade(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to approve

revokeUpgradeApproval

Revoke approval for a pending upgrade

Allows multi-sig signers to revoke their approval for pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function revokeUpgradeApproval(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to revoke approval for

executeUpgrade

Execute an upgrade after timelock and multi-sig approval

Executes a previously approved upgrade after timelock delay

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function executeUpgrade(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to execute

cancelUpgrade

Cancel a pending upgrade (only proposer or admin)

Allows proposer or admin to cancel a pending upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function cancelUpgrade(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to cancel

emergencyUpgrade

Emergency upgrade (bypasses timelock, requires emergency mode)

Performs immediate upgrade in emergency situations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyUpgrade(address newImplementation, string calldata description) external;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the emergency upgrade

addMultisigSigner

Add a multi-sig signer

Adds a new multi-sig signer to the approval process

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function addMultisigSigner(address signer) external;

Parameters

NameTypeDescription
signeraddressAddress of the signer to add

removeMultisigSigner

Remove a multi-sig signer

Removes a multi-sig signer from the approval process

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function removeMultisigSigner(address signer) external;

Parameters

NameTypeDescription
signeraddressAddress of the signer to remove

toggleEmergencyMode

Toggle emergency mode

Enables or disables emergency mode for immediate upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function toggleEmergencyMode(bool enabled, string calldata reason) external;

Parameters

NameTypeDescription
enabledboolWhether to enable emergency mode
reasonstringReason for the emergency mode change

getPendingUpgrade

Get pending upgrade details

Returns detailed information about a pending upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPendingUpgrade(address implementation) external view returns (PendingUpgrade memory upgrade);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
upgradePendingUpgradePending upgrade details

canExecuteUpgrade

Check if an upgrade can be executed

Checks if the timelock delay has passed and upgrade can be executed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function canExecuteUpgrade(address implementation) external view returns (bool canExecute);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
canExecuteboolWhether the upgrade can be executed

currentTime

Get canonical protocol time from the shared time provider

Exposes the time source used for governance delays and upgrade scheduling.

Notes:

  • security: Read-only view into canonical protocol time source

  • validation: No input validation required

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Public interface method

  • oracle: No oracle dependencies

function currentTime() external view returns (uint256 nowTs);

Returns

NameTypeDescription
nowTsuint256Current protocol timestamp

hasUpgradeApproval

Get upgrade approval status for a signer

Checks if a specific signer has approved a specific upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasUpgradeApproval(address signer, address implementation) external view returns (bool approved);

Parameters

NameTypeDescription
signeraddressAddress of the signer
implementationaddressAddress of the implementation

Returns

NameTypeDescription
approvedboolWhether the signer has approved the upgrade

getMultisigSigners

Get all multi-sig signers

Returns array of all authorized multi-sig signers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getMultisigSigners() external view returns (address[] memory signers);

Returns

NameTypeDescription
signersaddress[]Array of signer addresses

pendingUpgrades

Returns pending upgrade details for an implementation

Maps implementation address to pending upgrade information

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pendingUpgrades(address)
    external
    view
    returns (
        address implementation,
        address proposingProxy,
        uint256 proposedAt,
        uint256 executableAt,
        uint256 expiryAt,
        string memory description,
        bool isEmergency,
        address proposer
    );

Parameters

NameTypeDescription
<none>address

Returns

NameTypeDescription
implementationaddressAddress of the new implementation
proposingProxyaddressProxy contract that initiated the upgrade
proposedAtuint256Timestamp when upgrade was proposed
executableAtuint256Timestamp when upgrade can be executed
expiryAtuint256Timestamp when upgrade proposal expires
descriptionstringDescription of the upgrade
isEmergencyboolWhether this is an emergency upgrade
proposeraddressAddress of the proposer

multisigSigners

Checks if an address is a multi-sig signer

Returns true if the address is authorized as a multi-sig signer

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function multisigSigners(address signer) external view returns (bool);

Parameters

NameTypeDescription
signeraddressThe address to check

Returns

NameTypeDescription
<none>boolTrue if the address is a multi-sig signer

multisigSignerCount

Returns the total number of multi-sig signers

Returns the count of authorized multi-sig signers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function multisigSignerCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total number of multi-sig signers

upgradeApprovals

Checks if a signer has approved an upgrade

Returns true if the signer has approved the specific upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeApprovals(address signer, address newImplementation) external view returns (bool);

Parameters

NameTypeDescription
signeraddressThe address of the signer
newImplementationaddressThe address of the new implementation

Returns

NameTypeDescription
<none>boolTrue if the signer has approved the upgrade

upgradeApprovalCount

Returns the number of approvals for an upgrade

Returns the count of approvals for a specific upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeApprovalCount(address newImplementation) external view returns (uint256);

Parameters

NameTypeDescription
newImplementationaddressThe address of the new implementation

Returns

NameTypeDescription
<none>uint256Number of approvals for the upgrade

emergencyMode

Returns whether emergency mode is enabled

Indicates if emergency mode is currently active

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyMode() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if emergency mode is enabled

UPGRADE_DELAY

Returns the default upgrade delay

Minimum delay required for upgrades (in seconds)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADE_DELAY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Default upgrade delay in seconds

MAX_UPGRADE_DELAY

Returns the maximum allowed upgrade delay

Maximum delay that can be set for upgrades (in seconds)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MAX_UPGRADE_DELAY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Maximum upgrade delay in seconds

MIN_MULTISIG_APPROVALS

Returns the minimum required multi-sig approvals

Minimum number of approvals required to execute an upgrade

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MIN_MULTISIG_APPROVALS() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Minimum number of required approvals

MAX_MULTISIG_SIGNERS

Returns the maximum allowed multi-sig signers

Maximum number of multi-sig signers that can be added

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MAX_MULTISIG_SIGNERS() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Maximum number of multi-sig signers

UPGRADE_PROPOSER_ROLE

Returns the upgrade proposer role identifier

Role that can propose upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADE_PROPOSER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrade proposer role bytes32 identifier

UPGRADE_EXECUTOR_ROLE

Returns the upgrade executor role identifier

Role that can execute upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADE_EXECUTOR_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrade executor role bytes32 identifier

EMERGENCY_UPGRADER_ROLE

Returns the emergency upgrader role identifier

Role that can perform emergency upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function EMERGENCY_UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The emergency upgrader role bytes32 identifier

MULTISIG_MANAGER_ROLE

Returns the multi-sig manager role identifier

Role that can manage multi-sig signers

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MULTISIG_MANAGER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The multi-sig manager role bytes32 identifier

Events

UpgradeProposed

event UpgradeProposed(
    address indexed implementation,
    uint256 proposedAt,
    uint256 executableAt,
    string description,
    address indexed proposer
);

UpgradeApproved

event UpgradeApproved(address indexed implementation, address indexed signer, uint256 approvalCount);

UpgradeExecuted

event UpgradeExecuted(address indexed implementation, address indexed executor, uint256 executedAt);

UpgradeCancelled

event UpgradeCancelled(address indexed implementation, address indexed canceller);

MultisigSignerAdded

event MultisigSignerAdded(address indexed signer);

MultisigSignerRemoved

event MultisigSignerRemoved(address indexed signer);

EmergencyModeToggled

event EmergencyModeToggled(bool enabled, string reason);

Structs

PendingUpgrade

struct PendingUpgrade {
    address implementation;
    address proposingProxy; // proxy that initiated this upgrade
    uint256 proposedAt;
    uint256 executableAt;
    uint256 expiryAt; // proposal expires after MAX_PROPOSAL_AGE
    string description;
    bool isEmergency;
    address proposer;
}

IUserPool

Git Source

Title: IUserPool

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the UserPool managing deposits, staking, and yield

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the user pool

Sets up the user pool with initial configuration and assigns roles to admin

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _vault,
    address _oracle,
    address _yieldShift,
    address _timelock,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_qeuroaddressQEURO token address
_usdcaddressUSDC token address
_vaultaddressVault contract address
_oracleaddressOracle contract address
_yieldShiftaddressYieldShift contract address
_timelockaddressTimelock contract address
_treasuryaddressTreasury address

deposit

Deposit USDC to mint QEURO and join the pool

Converts USDC to QEURO and adds user to the pool for yield distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function deposit(uint256[] calldata usdcAmounts, uint256[] calldata minQeuroOuts)
    external
    returns (uint256[] memory qeuroMintedAmounts);

Parameters

NameTypeDescription
usdcAmountsuint256[]Amounts of USDC to deposit
minQeuroOutsuint256[]Minimum QEURO expected per deposit (slippage protection)

Returns

NameTypeDescription
qeuroMintedAmountsuint256[]Amounts of QEURO minted to user

withdraw

Withdraw USDC by burning QEURO

Converts QEURO back to USDC and removes user from the pool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function withdraw(uint256[] calldata qeuroAmounts, uint256[] calldata minUsdcOuts)
    external
    returns (uint256[] memory usdcReceivedAmounts);

Parameters

NameTypeDescription
qeuroAmountsuint256[]Amounts of QEURO to burn
minUsdcOutsuint256[]Minimum USDC expected per withdrawal

Returns

NameTypeDescription
usdcReceivedAmountsuint256[]USDC received by user

stake

Stake QEURO to earn staking rewards

Locks QEURO tokens to earn staking rewards with cooldown period

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function stake(uint256[] calldata qeuroAmounts) external;

Parameters

NameTypeDescription
qeuroAmountsuint256[]Amounts of QEURO to stake

requestUnstake

Request to unstake staked QEURO (starts cooldown)

Initiates unstaking process with cooldown period before final withdrawal

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function requestUnstake(uint256 qeuroAmount) external;

Parameters

NameTypeDescription
qeuroAmountuint256Amount to unstake

unstake

Finalize unstake after cooldown

Completes the unstaking process after cooldown period has passed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unstake() external;

getUserInfo

Get detailed user info

Returns comprehensive user information including balances and staking data

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getUserInfo(address user)
    external
    view
    returns (
        uint256 qeuroBalance,
        uint256 stakedAmount,
        uint256 pendingRewards,
        uint256 depositHistory,
        uint256 lastStakeTime,
        uint256 unstakeRequestTime,
        uint256 unstakeAmount
    );

Parameters

NameTypeDescription
useraddressAddress to query

Returns

NameTypeDescription
qeuroBalanceuint256QEURO balance from deposits
stakedAmountuint256QEURO amount staked
pendingRewardsuint256Pending staking rewards
depositHistoryuint256Total historical deposits
lastStakeTimeuint256Timestamp of last stake
unstakeRequestTimeuint256Timestamp of unstake request
unstakeAmountuint256Amount currently requested to unstake

getTotalDeposits

Current user-side pool size in USDC terms

Returns live user pool TVL in USDC equivalent; historical deposit counters are exposed separately.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getTotalDeposits() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current user pool size in USDC equivalent

getTotalStakes

Total QEURO staked in the pool

Returns the total amount of QEURO staked by all users

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getTotalStakes() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total staked QEURO amount

getPoolMetrics

Summary pool metrics

Returns comprehensive pool statistics and metrics

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getPoolMetrics()
    external
    view
    returns (uint256 totalUsers_, uint256 averageDeposit, uint256 stakingRatio, uint256 poolTVL);

Returns

NameTypeDescription
totalUsers_uint256Number of users
averageDeposituint256Average deposit per user
stakingRatiouint256Staking ratio (bps)
poolTVLuint256Total value locked

calculateProjectedRewards

Calculate projected rewards for a staking duration

Calculates expected rewards for a given staking amount and duration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function calculateProjectedRewards(uint256 qeuroAmount, uint256 duration)
    external
    view
    returns (uint256 projectedRewards);

Parameters

NameTypeDescription
qeuroAmountuint256QEURO amount
durationuint256Duration in seconds

Returns

NameTypeDescription
projectedRewardsuint256Expected rewards amount

updateStakingParameters

Update staking parameters

Allows governance to update staking configuration parameters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateStakingParameters(uint256 _stakingAPY, uint256 _minStakeAmount, uint256 _unstakingCooldown) external;

Parameters

NameTypeDescription
_stakingAPYuint256New staking APY (bps)
_minStakeAmountuint256Minimum stake amount
_unstakingCooldownuint256Unstaking cooldown in seconds

setPerformanceFee

Set performance fee for staking rewards

Allows governance to update performance fee parameter

NOTE: Mint/redemption fees are set in QuantillonVault, not UserPool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates performanceFee <= 2000 bps (20%)

  • state-changes: Updates performanceFee state variable

  • events: None

  • errors: Reverts if fee exceeds maximum allowed

  • reentrancy: Not applicable

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: Not applicable

function setPerformanceFee(uint256 _performanceFee) external;

Parameters

NameTypeDescription
_performanceFeeuint256Performance fee on staking rewards (bps)

emergencyUnstake

Emergency unstake for a user by admin

Allows admin to emergency unstake for a user bypassing cooldown

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function emergencyUnstake(address user, address recipient) external;

Parameters

NameTypeDescription
useraddressUser address
recipientaddressAddress receiving the unstaked funds

pause

Pause user pool operations

Emergency function to pause all pool operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function pause() external;

unpause

Unpause user pool operations

Resumes all pool operations after emergency pause

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unpause() external;

isPoolActive

Whether the pool operations are active (not paused)

Returns true if the pool is not paused and operations are active

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function isPoolActive() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if pool operations are active

hasRole

Checks if an account has a specific role

Returns true if the account has been granted the role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasRole(bytes32 role, address account) external view returns (bool);

Parameters

NameTypeDescription
rolebytes32The role to check
accountaddressThe account to check

Returns

NameTypeDescription
<none>boolTrue if the account has the role

getRoleAdmin

Gets the admin role for a given role

Returns the role that is the admin of the given role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function getRoleAdmin(bytes32 role) external view returns (bytes32);

Parameters

NameTypeDescription
rolebytes32The role to get admin for

Returns

NameTypeDescription
<none>bytes32The admin role

grantRole

Grants a role to an account

Can only be called by an account with the admin role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function grantRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to grant
accountaddressThe account to grant the role to

revokeRole

Revokes a role from an account

Can only be called by an account with the admin role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function revokeRole(bytes32 role, address account) external;

Parameters

NameTypeDescription
rolebytes32The role to revoke
accountaddressThe account to revoke the role from

renounceRole

Renounces a role from the caller

The caller gives up their own role

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function renounceRole(bytes32 role, address callerConfirmation) external;

Parameters

NameTypeDescription
rolebytes32The role to renounce
callerConfirmationaddressConfirmation that the caller is renouncing their own role

paused

Checks if the contract is paused

Returns true if the contract is currently paused

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue if paused, false otherwise

upgradeToAndCall

Upgrades the contract to a new implementation and calls a function

Can only be called by accounts with UPGRADER_ROLE

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function upgradeToAndCall(address newImplementation, bytes memory data) external payable;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract
databytesEncoded function call data

GOVERNANCE_ROLE

Returns the governance role identifier

Role that can update pool parameters and governance functions

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function GOVERNANCE_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The governance role bytes32 identifier

EMERGENCY_ROLE

Returns the emergency role identifier

Role that can pause the pool and perform emergency operations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function EMERGENCY_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The emergency role bytes32 identifier

UPGRADER_ROLE

Returns the upgrader role identifier

Role that can upgrade the contract implementation

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrader role bytes32 identifier

MAX_REWARD_PERIOD

Returns the number of blocks per day

Returns the maximum reward period

Used for reward calculations

Maximum duration for reward calculations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function MAX_REWARD_PERIOD() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of blocks per day

qeuro

Returns the QEURO token address

The euro-pegged stablecoin token used in the pool

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function qeuro() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the QEURO token contract

usdc

Returns the USDC token address

The collateral token used for deposits

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the USDC token contract

vault

Returns the vault contract address

The vault contract used for minting/burning QEURO

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function vault() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the vault contract

yieldShift

Returns the yield shift contract address

The contract managing yield distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function yieldShift() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the yield shift contract

stakingAPY

Returns the current staking APY

Annual percentage yield for staking (in basis points)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function stakingAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current staking APY in basis points

depositAPY

Returns the current deposit APY

Annual percentage yield for deposits (in basis points)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function depositAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current deposit APY in basis points

minStakeAmount

Returns the minimum stake amount

Minimum amount of QEURO required to stake

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function minStakeAmount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Minimum stake amount in QEURO

unstakingCooldown

Returns the unstaking cooldown period

Time in seconds before unstaking can be completed

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function unstakingCooldown() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Unstaking cooldown in seconds

performanceFee

Returns the performance fee

Fee charged on performance (in basis points)

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function performanceFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Performance fee in basis points

totalUserDeposits

Returns the total user deposits

Total USDC deposits across all users (in USDC decimals - 6)

Tracks the sum of all USDC deposits made by users

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalUserDeposits() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total user deposits in USDC (6 decimals)

totalStakes

Returns the total stakes

Total amount of QEURO staked by all users

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalStakes() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total staked QEURO amount

totalUsers

Returns the total number of users

Number of users who have deposited or staked

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalUsers() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total number of users

accumulatedYieldPerShare

Returns the accumulated yield per share

Used for calculating user rewards

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function accumulatedYieldPerShare() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Accumulated yield per share

lastYieldDistribution

Returns the last yield distribution timestamp

Timestamp of the last yield distribution

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function lastYieldDistribution() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Last yield distribution timestamp

totalYieldDistributed

Returns the total yield distributed

Total amount of yield distributed to users

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function totalYieldDistributed() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total yield distributed

userLastRewardBlock

Returns the last reward block for a user

Last block when user rewards were calculated

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function userLastRewardBlock(address user) external view returns (uint256);

Parameters

NameTypeDescription
useraddressThe user address

Returns

NameTypeDescription
<none>uint256Last reward block number

hasDeposited

Checks if a user has deposited

Returns true if the user has ever deposited

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function hasDeposited(address user) external view returns (bool);

Parameters

NameTypeDescription
useraddressThe user address

Returns

NameTypeDescription
<none>boolTrue if user has deposited

userInfo

Returns detailed user information

Returns comprehensive user data including balances and staking info

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function userInfo(address user)
    external
    view
    returns (
        uint256 qeuroBalance,
        uint256 stakedAmount,
        uint256 pendingRewards,
        uint256 depositHistory,
        uint256 lastStakeTime,
        uint256 unstakeRequestTime,
        uint256 unstakeAmount
    );

Parameters

NameTypeDescription
useraddressThe user address

Returns

NameTypeDescription
qeuroBalanceuint256QEURO balance from deposits
stakedAmountuint256QEURO amount staked
pendingRewardsuint256Pending staking rewards
depositHistoryuint256Total historical deposits
lastStakeTimeuint256Timestamp of last stake
unstakeRequestTimeuint256Timestamp of unstake request
unstakeAmountuint256Amount currently requested to unstake

recoverToken

Recovers ERC20 tokens sent by mistake

Allows governance to recover accidentally sent ERC20 tokens

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address
amountuint256Amount to transfer

recoverETH

Recovers ETH sent by mistake

Allows governance to recover accidentally sent ETH

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external;

IVersioned

Git Source

Title: IVersioned

Standard semantic-version getter implemented by every core Quantillon contract.

Read through a proxy, version() reflects the deployed IMPLEMENTATION (it is a pure getter returning a compile-time constant, so it occupies no storage slot and is safe to add to storage-frozen upgradeable contracts). It pairs with the off-chain provenance manifest deployments/{chainId}/versions.json (impl address + commit) so the deployed version of any contract is answerable from a single on-chain call. Bump per semver on any change to the implementing contract; enforced by make check-version-bump.

Functions

version

Returns the semantic version of the implementation.

Semver convention: PATCH = bugfix/internal logic, MINOR = new function or externally-observable behavior (ABI-additive), MAJOR = reserved (storage/ABI breaks are disallowed by the upgrade-safety gates).

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string, e.g. "1.0.0".

IYieldShift

Git Source

Functions

initialize

Initializes the YieldShift contract.

Sets up core roles, USDC token and optional initial dependencies.

Notes:

  • security: Validates non‑zero admin and USDC address, sets up access control.

  • validation: Reverts on invalid addresses; optional dependencies may be zero.

  • state-changes: Initializes roles, references and scalar defaults.

  • events: Emits implementation‑specific initialization events.

  • errors: Reverts with protocol‑specific validation errors.

  • reentrancy: Protected by initializer modifier in implementation.

  • access: External initializer; callable once.

  • oracle: No direct oracle dependency.

function initialize(
    address admin,
    address _usdc,
    address _userPool,
    address _hedgerPool,
    address _mockAaveVault,
    address _stQEUROFactory,
    address _timelock,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAddress receiving admin and governance roles.
_usdcaddressUSDC token address used for yield accounting.
_userPooladdressUserPool contract address (optional at deploy time).
_hedgerPooladdressHedgerPool contract address (optional at deploy time).
_mockAaveVaultaddressMockAaveVault contract address (optional at deploy time).
_stQEUROFactoryaddressstQEURO factory contract address (optional at deploy time).
_timelockaddressTimelock contract used for SecureUpgradeable.
_treasuryaddressTreasury address for recovery flows.

bootstrapDefaults

Governance bootstrap to set initial histories and default sources.

Lazily initializes TWAP histories and default yield source metadata after initialize.

Notes:

  • security: Restricted to governance; reads only already‑validated state.

  • validation: Reverts if caller lacks governance role.

  • state-changes: Records initial snapshots and default yield source mappings.

  • events: Emits no external events beyond those in implementation.

  • errors: Reverts with access‑control errors on unauthorized callers.

  • reentrancy: Not applicable – configuration only.

  • access: Governance‑only.

  • oracle: No oracle dependency.

function bootstrapDefaults() external;

updateYieldDistribution

Updates the yield distribution between user and hedger pools.

Recomputes currentYieldShift using eligible pool metrics and updates history.

Notes:

  • security: Callable by authorized roles; uses holding‑period protection against flash deposits.

  • validation: Reverts if dependencies are misconfigured.

  • state-changes: Updates currentYieldShift, lastUpdateTime and pool snapshots.

  • events: Emits YieldDistributionUpdated.

  • errors: Reverts with protocol‑specific config or math errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Typically callable by anyone or scheduled keeper, per implementation.

  • oracle: No direct oracle reads; relies on pool metrics.

function updateYieldDistribution() external;

addYield

Adds yield from an authorized source and allocates it between users and hedgers.

Transfers USDC from msg.sender, checks authorization and updates yield pools.

Notes:

  • security: Only authorized yield sources may call; validates source mapping.

  • validation: Reverts if transferred amount does not match yieldAmount within 1 wei.

  • state-changes: Updates yieldSources, totalYieldGenerated, userYieldPool, hedgerYieldPool.

  • events: Emits YieldAdded.

  • errors: Reverts with authorization or amount‑mismatch errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to whitelisted yield source contracts.

  • oracle: No direct oracle dependency.

function addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source) external;

Parameters

NameTypeDescription
vaultIduint256Target vault id receiving user-yield routing.
yieldAmountuint256Yield amount in USDC (6 decimals).
sourcebytes32Logical yield source identifier (e.g. keccak256("aave")).

claimHedgerYield

Claims accumulated hedger yield for a specific hedger.

Transfers pending hedger yield from hedgerYieldPool to hedger.

Notes:

  • security: Callable by hedger or HedgerPool; enforces authorization.

  • validation: Reverts if pool has insufficient yield.

  • state-changes: Updates hedgerPendingYield, hedgerLastClaim, hedgerYieldPool, totalYieldDistributed.

  • events: Emits HedgerYieldClaimed.

  • errors: Reverts with insufficient‑yield or access errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to hedger or HedgerPool.

  • oracle: No direct oracle dependency.

function claimHedgerYield(address hedger) external returns (uint256 yieldAmount);

Parameters

NameTypeDescription
hedgeraddressAddress of the hedger.

Returns

NameTypeDescription
yieldAmountuint256Amount of USDC yield transferred.

updateLastDepositTime

Updates the last deposit timestamp for a user.

Called by UserPool / HedgerPool so holding‑period logic can be enforced.

Notes:

  • security: Only callable by UserPool or HedgerPool contracts.

  • validation: Reverts on unauthorized caller.

  • state-changes: Updates lastDepositTime[user].

  • events: None.

  • errors: Reverts with authorization error.

  • reentrancy: Not applicable – simple storage write.

  • access: Restricted to pools.

  • oracle: No oracle dependency.

function updateLastDepositTime(address user) external;

Parameters

NameTypeDescription
useraddressAddress whose last deposit time is updated.

updateYieldAllocation

Updates per‑user or per‑hedger yield allocation.

Called by pool logic to adjust individual pending yield balances.

Notes:

  • security: Restricted to yield‑manager roles via AccessControlLibrary.

  • validation: Reverts on unauthorized caller.

  • state-changes: Updates userPendingYield or hedgerPendingYield.

  • events: None.

  • errors: Reverts with access‑control errors.

  • reentrancy: Not applicable – simple storage updates.

  • access: Restricted to YieldManager role.

  • oracle: No oracle dependency.

function updateYieldAllocation(address user, uint256 amount, bool isUser) external;

Parameters

NameTypeDescription
useraddressUser or hedger address.
amountuint256Allocation delta amount.
isUserboolTrue if user is a UserPool participant, false if hedger.

configureYieldModel

Batch‑updates all yield model parameters.

See YieldShift.configureYieldModel for implementation semantics.

Notes:

  • security: Restricted to governance.

  • validation: Reverts when parameters are out of allowed bounds.

  • state-changes: Updates scalar configuration in storage.

  • events: None.

  • errors: Protocol‑specific config errors.

  • reentrancy: Not applicable.

  • access: Governance‑only.

  • oracle: No oracle dependency.

function configureYieldModel(YieldModelConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgYieldModelConfigNew yield model configuration.

configureDependencies

Batch‑updates core dependency addresses.

See YieldShift.configureDependencies for implementation semantics.

Notes:

  • security: Restricted to governance; validates non‑zero addresses.

  • validation: Reverts on invalid or zero addresses.

  • state-changes: Updates pool, vault, stQEURO and treasury references.

  • events: None.

  • errors: Protocol‑specific config errors.

  • reentrancy: Not applicable.

  • access: Governance‑only.

  • oracle: No oracle dependency.

function configureDependencies(YieldDependencyConfig calldata cfg) external;

Parameters

NameTypeDescription
cfgYieldDependencyConfigNew dependency configuration.

setYieldSourceAuthorization

Sets authorization status and yield type for a yield source.

See YieldShift.setYieldSourceAuthorization for implementation semantics.

Notes:

  • security: Restricted to governance; prevents arbitrary contracts from adding yield.

  • validation: Reverts on zero source address.

  • state-changes: Updates authorization and source‑type mappings.

  • events: None.

  • errors: Protocol‑specific validation errors.

  • reentrancy: Not applicable.

  • access: Governance‑only.

  • oracle: No oracle dependency.

function setYieldSourceAuthorization(address source, bytes32 yieldType, bool authorized) external;

Parameters

NameTypeDescription
sourceaddressAddress of the yield source.
yieldTypebytes32Type/category of yield generated by the source.
authorizedboolTrue to authorize, false to deauthorize.

setSourceVaultBinding

Binds a source to a single vault id for optional strict routing.

Governance hook used to restrict a source to one vault when enforcement is enabled.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Reverts on zero source or invalid vault id per implementation rules.

  • state-changes: Updates source-to-vault binding map.

  • events: Emits binding update event in implementation.

  • errors: Reverts on invalid inputs or unauthorized access.

  • reentrancy: Not applicable.

  • access: Governance-only.

  • oracle: No oracle dependency.

function setSourceVaultBinding(address source, uint256 vaultId) external;

Parameters

NameTypeDescription
sourceaddressYield source address.
vaultIduint256Vault id the source is allowed to target in strict mode.

clearSourceVaultBinding

Clears a source-to-vault binding.

Governance hook that removes strict routing assignment for a source.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Reverts on zero source per implementation rules.

  • state-changes: Deletes source-to-vault binding entry.

  • events: Emits binding clear event in implementation.

  • errors: Reverts on invalid inputs or unauthorized access.

  • reentrancy: Not applicable.

  • access: Governance-only.

  • oracle: No oracle dependency.

function clearSourceVaultBinding(address source) external;

Parameters

NameTypeDescription
sourceaddressYield source address.

setSourceVaultBindingEnforcement

Enables or disables strict source-to-vault binding enforcement.

Governance toggle controlling whether addYield must respect source bindings.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Boolean input only; no additional validation required.

  • state-changes: Updates binding-enforcement flag.

  • events: Emits enforcement toggle event in implementation.

  • errors: Reverts on unauthorized access.

  • reentrancy: Not applicable.

  • access: Governance-only.

  • oracle: No oracle dependency.

function setSourceVaultBindingEnforcement(bool enabled) external;

Parameters

NameTypeDescription
enabledboolTrue to enforce binding in addYield.

emergencyYieldDistribution

Executes an emergency yield distribution with explicit pool amounts.

Transfers specified portions of yield pool balances to UserPool and HedgerPool.

Notes:

  • security: Restricted to emergency role; validates pool sufficiency.

  • validation: Reverts if requested amounts exceed available pools.

  • state-changes: Decreases internal pools and transfers USDC to pools.

  • events: Emits implementation‑specific emergency distribution events.

  • errors: Reverts with insufficient‑yield errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Emergency‑only.

  • oracle: No oracle dependency.

function emergencyYieldDistribution(uint256 userAmount, uint256 hedgerAmount) external;

Parameters

NameTypeDescription
userAmountuint256Amount to distribute to user pool.
hedgerAmountuint256Amount to distribute to hedger pool.

pauseYieldDistribution

Pauses yield distribution operations.

Emergency function to halt yield‑related state changes.

Notes:

  • security: Restricted to emergency role.

  • validation: None.

  • state-changes: Sets paused state to true.

  • events: Emits Paused.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Emergency‑only.

  • oracle: No oracle dependency.

function pauseYieldDistribution() external;

resumeYieldDistribution

Resumes yield distribution operations after a pause.

Clears the paused state to restore normal operation.

Notes:

  • security: Restricted to emergency role.

  • validation: None.

  • state-changes: Sets paused state to false.

  • events: Emits Unpaused.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Emergency‑only.

  • oracle: No oracle dependency.

function resumeYieldDistribution() external;

isYieldSourceAuthorized

Checks if a yield source is authorized for a given yield type.

Reads the authorization and yield‑type mapping configured by governance.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function isYieldSourceAuthorized(address source, bytes32 yieldType) external view returns (bool authorized);

Parameters

NameTypeDescription
sourceaddressAddress of the yield source.
yieldTypebytes32Yield type identifier.

Returns

NameTypeDescription
authorizedboolTrue if source is authorized for yieldType.

checkAndUpdateYieldDistribution

Checks current conditions and updates yield distribution if required.

Uses TWAP metrics and tolerance thresholds to decide whether to call updateYieldDistribution.

Notes:

  • security: Public keeper function; guarded by internal conditions.

  • validation: None.

  • state-changes: May update currentYieldShift, snapshots and timestamps indirectly.

  • events: Emits YieldDistributionUpdated when distribution is adjusted.

  • errors: None when conditions are not met; may revert on configuration errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Public/keeper‑triggered.

  • oracle: No oracle dependency.

function checkAndUpdateYieldDistribution() external;

forceUpdateYieldDistribution

Forces an immediate yield‑distribution update regardless of conditions.

Governance escape hatch calling updateYieldDistribution via this to preserve modifiers.

Notes:

  • security: Restricted to governance; overrides normal TWAP/tolerance checks.

  • validation: None beyond access‑control.

  • state-changes: Same as updateYieldDistribution.

  • events: Emits YieldDistributionUpdated.

  • errors: Reverts with configuration or math errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Governance‑only.

  • oracle: No oracle dependency.

function forceUpdateYieldDistribution() external;

getYieldDistributionBreakdown

Returns a breakdown of yield between user and hedger pools.

Aggregates userYieldPool and hedgerYieldPool into a distribution ratio.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for dashboards and analytics.

  • oracle: No oracle dependency.

function getYieldDistributionBreakdown()
    external
    view
    returns (uint256 userYieldPool_, uint256 hedgerYieldPool_, uint256 distributionRatio);

Returns

NameTypeDescription
userYieldPool_uint256Current user yield pool balance.
hedgerYieldPool_uint256Current hedger yield pool balance.
distributionRatiouint256User share of total yield pool in basis points.

getPoolMetrics

Returns current pool metrics for user and hedger pools.

Exposes pool sizes, current ratio and target ratio for monitoring.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function getPoolMetrics()
    external
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio, uint256 targetRatio);

Returns

NameTypeDescription
userPoolSizeuint256Current user pool size.
hedgerPoolSizeuint256Current hedger pool size.
poolRatiouint256Ratio of user to hedger pools.
targetRatiouint256Target pool ratio configured in the model.

calculateOptimalYieldShift

Calculates the optimal yield shift based on current pool metrics.

Purely view‑based recommendation; does not update state.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – off‑chain controllers may act on it.

  • oracle: No oracle dependency.

function calculateOptimalYieldShift() external view returns (uint256 optimalShift, uint256 currentDeviation);

Returns

NameTypeDescription
optimalShiftuint256Recommended yield shift in basis points.
currentDeviationuint256Absolute deviation between current and optimal shifts.

getYieldSources

Returns aggregated yield amounts by source category.

Splits yieldSources into Aave, protocol fees, interest differential and other.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for analytics.

  • oracle: No oracle dependency.

function getYieldSources()
    external
    view
    returns (uint256 aaveYield, uint256 protocolFees, uint256 interestDifferential, uint256 otherSources);

Returns

NameTypeDescription
aaveYielduint256Yield attributed to Aave.
protocolFeesuint256Yield attributed to protocol fees.
interestDifferentialuint256Yield attributed to interest‑rate differential.
otherSourcesuint256Residual yield not in the known categories.

getHistoricalYieldShift

Returns a compact summary of yield‑shift behavior over a period.

Implementation currently returns a representative single value for the window.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for historical analytics.

  • oracle: No oracle dependency.

function getHistoricalYieldShift(uint256 period)
    external
    view
    returns (uint256 averageShift, uint256 maxShift, uint256 minShift, uint256 volatility);

Parameters

NameTypeDescription
perioduint256Look‑back period in seconds.

Returns

NameTypeDescription
averageShiftuint256Representative shift in the period.
maxShiftuint256Same as averageShift in compact mode.
minShiftuint256Same as averageShift in compact mode.
volatilityuint256Always 0 in compact summary mode.

getYieldPerformanceMetrics

Returns compact performance metrics for yield operations.

Aggregates total distributed yield, current pools and efficiency ratio.

Notes:

  • security: View‑only; no access restriction.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public – for dashboards and reporting.

  • oracle: No oracle dependency.

function getYieldPerformanceMetrics()
    external
    view
    returns (
        uint256 totalYieldDistributed_,
        uint256 averageUserYield,
        uint256 averageHedgerYield,
        uint256 yieldEfficiency
    );

Returns

NameTypeDescription
totalYieldDistributed_uint256Total yield distributed so far.
averageUserYielduint256Current user yield pool balance.
averageHedgerYielduint256Current hedger yield pool balance.
yieldEfficiencyuint256Distributed/generate ratio in basis points.

currentYieldShift

Returns the current yield shift between users and hedgers.

This value drives how new yield is split between userYieldPool and hedgerYieldPool.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function currentYieldShift() external view returns (uint256 shift);

Returns

NameTypeDescription
shiftuint256Current shift value in basis points.

totalYieldGenerated

Returns total yield generated across all sources.

Monotonically increasing counter of all yield ever added via addYield.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function totalYieldGenerated() external view returns (uint256 total);

Returns

NameTypeDescription
totaluint256Total generated yield.

totalYieldDistributed

Returns total yield distributed so far.

Tracks how much of totalYieldGenerated has actually been paid out.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function totalYieldDistributed() external view returns (uint256 total);

Returns

NameTypeDescription
totaluint256Total distributed yield.

userYieldPool

Returns current user yield pool balance.

Amount of yield currently earmarked for users but not yet claimed.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function userYieldPool() external view returns (uint256 pool);

Returns

NameTypeDescription
pooluint256User yield pool amount.

hedgerYieldPool

Returns current hedger yield pool balance.

Amount of yield currently earmarked for hedgers but not yet claimed.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function hedgerYieldPool() external view returns (uint256 pool);

Returns

NameTypeDescription
pooluint256Hedger yield pool amount.

userPendingYield

Returns pending yield for a user.

Per-user pending-yield bookkeeping. NOTE: userYieldPool is never funded by the normal addYield flow (user yield accrues via stQEURO), so this value is vestigial and not claimable on-chain.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function userPendingYield(address user) external view returns (uint256 amount);

Parameters

NameTypeDescription
useraddressUser address.

Returns

NameTypeDescription
amountuint256Pending yield amount.

hedgerPendingYield

Returns pending yield for a hedger.

Reads per‑hedger pending yield that can be claimed via claimHedgerYield.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function hedgerPendingYield(address hedger) external view returns (uint256 amount);

Parameters

NameTypeDescription
hedgeraddressHedger address.

Returns

NameTypeDescription
amountuint256Pending yield amount.

userLastClaim

Returns last claim timestamp for a user.

Used together with lastDepositTime to enforce holding‑period rules.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function userLastClaim(address user) external view returns (uint256 timestamp);

Parameters

NameTypeDescription
useraddressUser address.

Returns

NameTypeDescription
timestampuint256Last claim time.

hedgerLastClaim

Returns last claim timestamp for a hedger.

Used to monitor hedger reward activity and potential abuse.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function hedgerLastClaim(address hedger) external view returns (uint256 timestamp);

Parameters

NameTypeDescription
hedgeraddressHedger address.

Returns

NameTypeDescription
timestampuint256Last claim time.

baseYieldShift

Returns the base yield shift configuration parameter.

Baseline user share when pools are perfectly balanced.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function baseYieldShift() external view returns (uint256 base);

Returns

NameTypeDescription
baseuint256Base shift value (bps).

maxYieldShift

Returns the maximum yield shift configuration parameter.

Upper bound for how far currentYieldShift may move away from the base.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function maxYieldShift() external view returns (uint256 maxShift);

Returns

NameTypeDescription
maxShiftuint256Maximum shift value (bps).

adjustmentSpeed

Returns the adjustment speed configuration parameter.

Controls how quickly currentYieldShift moves toward the optimal shift.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function adjustmentSpeed() external view returns (uint256 speed);

Returns

NameTypeDescription
speeduint256Adjustment speed in basis points.

targetPoolRatio

Returns the target pool ratio configuration parameter.

Ideal ratio of user‑pool size to hedger‑pool size used in shift calculations.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function targetPoolRatio() external view returns (uint256 ratio);

Returns

NameTypeDescription
ratiouint256Target user/hedger pool ratio in basis points.

lastUpdateTime

Returns the last time yield distribution was updated.

Timestamp used to enforce minimum intervals and TWAP windows between updates.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function lastUpdateTime() external view returns (uint256 timestamp);

Returns

NameTypeDescription
timestampuint256Last update time.

paused

Returns whether yield distribution is currently paused.

When true, state‑changing yield operations are halted by Pausable.

Notes:

  • security: View‑only.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: No oracle dependency.

function paused() external view returns (bool isPaused);

Returns

NameTypeDescription
isPausedboolTrue if paused, false otherwise.

Structs

YieldModelConfig

struct YieldModelConfig {
    uint256 baseYieldShift;
    uint256 maxYieldShift;
    uint256 adjustmentSpeed;
    uint256 targetPoolRatio;
}

YieldDependencyConfig

struct YieldDependencyConfig {
    address userPool;
    address hedgerPool;
    address mockAaveVault;
    address stQEUROFactory;
    address treasury;
}

IstQEURO

Git Source

Title: IstQEURO

Minimal ERC-4626-oriented interface for stQEURO vault tokens.

Functions

asset

Returns the underlying ERC-20 asset managed by the vault.

Implementations should return the QEURO token address used by the ERC-4626 vault.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function asset() external view returns (address);

Returns

NameTypeDescription
<none>addressunderlyingAsset Address of the underlying QEURO asset.

totalAssets

Returns the total QEURO assets currently backing the vault.

Implementations should include principal and compounded yield held by the ERC-4626 vault.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function totalAssets() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256managedAssets Total QEURO assets managed by the vault.

convertToShares

Converts a QEURO asset amount into the equivalent share amount.

Mirrors ERC-4626 share-conversion math using the current vault exchange rate.

Notes:

  • security: Read-only helper.

  • validation: Uses the current vault accounting model and rounding rules.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function convertToShares(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to convert.

Returns

NameTypeDescription
sharesuint256Equivalent stQEURO shares for assets.

convertToAssets

Converts a stQEURO share amount into the equivalent asset amount.

Mirrors ERC-4626 asset-conversion math using the current vault exchange rate.

Notes:

  • security: Read-only helper.

  • validation: Uses the current vault accounting model and rounding rules.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function convertToAssets(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to convert.

Returns

NameTypeDescription
assetsuint256Equivalent QEURO assets for shares.

previewDeposit

Previews how many shares a deposit would mint.

Mirrors ERC-4626 preview math without transferring assets.

Notes:

  • security: Read-only helper.

  • validation: Uses current vault accounting and rounding behavior.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function previewDeposit(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to preview.

Returns

NameTypeDescription
sharesuint256Estimated stQEURO shares for the deposit.

previewMint

Previews how many assets would be required to mint a target share amount.

Mirrors ERC-4626 preview math without transferring assets.

Notes:

  • security: Read-only helper.

  • validation: Uses current vault accounting and rounding behavior.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function previewMint(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to preview.

Returns

NameTypeDescription
assetsuint256Estimated QEURO assets required to mint shares.

previewWithdraw

Previews how many shares would be burned to withdraw a target asset amount.

Mirrors ERC-4626 preview math without transferring assets.

Notes:

  • security: Read-only helper.

  • validation: Uses current vault accounting and rounding behavior.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function previewWithdraw(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to preview.

Returns

NameTypeDescription
sharesuint256Estimated stQEURO shares burned for the withdrawal.

previewRedeem

Previews how many assets would be returned for a target share redemption.

Mirrors ERC-4626 preview math without transferring assets.

Notes:

  • security: Read-only helper.

  • validation: Uses current vault accounting and rounding behavior.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function previewRedeem(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to preview.

Returns

NameTypeDescription
assetsuint256Estimated QEURO assets returned for redeeming shares.

deposit

Deposits QEURO and mints stQEURO shares to a receiver.

Implementations should follow ERC-4626 deposit semantics and emit a Deposit event.

Notes:

  • security: Implementations should apply pause, allowance, and asset-transfer protections.

  • validation: Implementations validate deposit amount, receiver, and available limits.

  • state-changes: Transfers QEURO into the vault and mints stQEURO shares.

  • events: Emits the standard ERC-4626 Deposit event in implementation.

  • errors: Reverts on invalid input, paused state, or ERC-20/ERC-4626 failures.

  • reentrancy: Implementation should guard integrated transfer flows as needed.

  • access: Public.

  • oracle: Not applicable.

function deposit(uint256 assets, address receiver) external returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to deposit.
receiveraddressAddress receiving the minted stQEURO shares.

Returns

NameTypeDescription
sharesuint256Amount of stQEURO shares minted.

mint

Mints a target share amount by supplying the required QEURO assets.

Implementations should follow ERC-4626 mint semantics and emit a Deposit event.

Notes:

  • security: Implementations should apply pause, allowance, and asset-transfer protections.

  • validation: Implementations validate share amount, receiver, and available limits.

  • state-changes: Transfers QEURO into the vault and mints stQEURO shares.

  • events: Emits the standard ERC-4626 Deposit event in implementation.

  • errors: Reverts on invalid input, paused state, or ERC-20/ERC-4626 failures.

  • reentrancy: Implementation should guard integrated transfer flows as needed.

  • access: Public.

  • oracle: Not applicable.

function mint(uint256 shares, address receiver) external returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to mint.
receiveraddressAddress receiving the minted stQEURO shares.

Returns

NameTypeDescription
assetsuint256Amount of QEURO assets required for the mint.

withdraw

Withdraws QEURO assets from the vault.

Implementations should follow ERC-4626 withdraw semantics and emit a Withdraw event.

Notes:

  • security: Implementations should apply pause, allowance, and asset-transfer protections.

  • validation: Implementations validate asset amount, receiver/owner, and available limits.

  • state-changes: Burns stQEURO shares and transfers QEURO assets out of the vault.

  • events: Emits the standard ERC-4626 Withdraw event in implementation.

  • errors: Reverts on invalid input, paused state, insufficient balances, or ERC-20/ERC-4626 failures.

  • reentrancy: Implementation should guard integrated transfer flows as needed.

  • access: Public.

  • oracle: Not applicable.

function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of QEURO assets to withdraw.
receiveraddressAddress receiving the withdrawn QEURO.
owneraddressShare owner whose balance and allowance are consumed.

Returns

NameTypeDescription
sharesuint256Amount of stQEURO shares burned.

redeem

Redeems stQEURO shares for the underlying QEURO assets.

Implementations should follow ERC-4626 redeem semantics and emit a Withdraw event.

Notes:

  • security: Implementations should apply pause, allowance, and asset-transfer protections.

  • validation: Implementations validate share amount, receiver/owner, and available limits.

  • state-changes: Burns stQEURO shares and transfers QEURO assets out of the vault.

  • events: Emits the standard ERC-4626 Withdraw event in implementation.

  • errors: Reverts on invalid input, paused state, insufficient balances, or ERC-20/ERC-4626 failures.

  • reentrancy: Implementation should guard integrated transfer flows as needed.

  • access: Public.

  • oracle: Not applicable.

function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of stQEURO shares to redeem.
receiveraddressAddress receiving the redeemed QEURO.
owneraddressShare owner whose balance and allowance are consumed.

Returns

NameTypeDescription
assetsuint256Amount of QEURO assets returned.

balanceOf

Returns the current share balance for an owner.

Mirrors the ERC-20 balance view for stQEURO shares.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function balanceOf(address owner) external view returns (uint256 shares);

Parameters

NameTypeDescription
owneraddressAccount whose share balance is being queried.

Returns

NameTypeDescription
sharesuint256Current stQEURO share balance of owner.

totalSupply

Returns the total outstanding supply of stQEURO shares.

Mirrors the ERC-20 total supply view for the vault share token.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function totalSupply() external view returns (uint256 sharesSupply);

Returns

NameTypeDescription
sharesSupplyuint256Total stQEURO shares currently issued.

yieldFee

Returns the configured yield fee for compounded vault yield.

Implementations generally express the fee in basis points.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function yieldFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256feeBps Current yield fee in basis points.

updateYieldParameters

Updates the yield fee applied to compounded vault yield.

Implementations typically restrict this governance action and validate basis-point caps.

Notes:

  • security: Restricted in implementation to governance or admin roles.

  • validation: Implementations validate _yieldFee against configured fee limits.

  • state-changes: Updates the stored yield-fee configuration.

  • events: Emits implementation-defined yield-parameter update events.

  • errors: Reverts on invalid fee values or missing privileges in implementation.

  • reentrancy: Not applicable.

  • access: Restricted in implementation to governance or admin roles.

  • oracle: Not applicable.

function updateYieldParameters(uint256 _yieldFee) external;

Parameters

NameTypeDescription
_yieldFeeuint256New yield fee in basis points.

vaultName

Returns the human-readable vault name associated with the share series.

Used by frontends and admin tooling to distinguish vault-specific stQEURO series.

Notes:

  • security: Read-only helper.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: Not applicable.

function vaultName() external view returns (string memory);

Returns

NameTypeDescription
<none>stringname Vault name or suffix configured for the share token.

Contents

AccessControlLibrary

Git Source

Title: AccessControlLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Access control functions for Quantillon Protocol

Main characteristics:

  • Role-based access control validation functions
  • Address and amount validation utilities
  • Reduces contract bytecode size through library extraction
  • Provides standardized error handling for access control

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

onlyGovernance

Ensures the caller has governance role

Reverts with NotGovernance if caller lacks GOVERNANCE_ROLE

Notes:

  • security: Validates caller has GOVERNANCE_ROLE before allowing access

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: Throws NotGovernance if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyGovernance(AccessControlUpgradeable accessControl) internal view;

Parameters

NameTypeDescription
accessControlAccessControlUpgradeableThe access control contract to check roles against

onlyEmergencyRole

Ensures the caller has emergency role

Reverts with NotEmergencyRole if caller lacks EMERGENCY_ROLE

Notes:

  • security: Validates caller has EMERGENCY_ROLE before allowing access

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: Throws NotEmergencyRole if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyEmergencyRole(AccessControlUpgradeable accessControl) internal view;

Parameters

NameTypeDescription
accessControlAccessControlUpgradeableThe access control contract to check roles against

onlyYieldManager

Ensures the caller has yield manager role

Reverts with NotYieldManager if caller lacks YIELD_MANAGER_ROLE

Notes:

  • security: Validates caller has YIELD_MANAGER_ROLE before allowing access

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: Throws NotYieldManager if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyYieldManager(AccessControlUpgradeable accessControl) internal view;

Parameters

NameTypeDescription
accessControlAccessControlUpgradeableThe access control contract to check roles against

onlyAdmin

Ensures the caller has admin role

Reverts with NotAdmin if caller lacks DEFAULT_ADMIN_ROLE

Notes:

  • security: Validates caller has DEFAULT_ADMIN_ROLE before allowing access

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: Throws NotAdmin if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyAdmin(AccessControlUpgradeable accessControl) internal view;

Parameters

NameTypeDescription
accessControlAccessControlUpgradeableThe access control contract to check roles against

validateAddress

Validates that an address is not the zero address

Reverts with InvalidAddress if address is zero

Notes:

  • security: Prevents zero address usage which could cause loss of funds

  • validation: Validates addr != address(0)

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidAddress if address is zero

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function validateAddress(address addr) internal pure;

Parameters

NameTypeDescription
addraddressThe address to validate

AdminFunctionsLibrary

Git Source

Title: AdminFunctionsLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Library for rarely used admin functions to reduce contract size

Main characteristics:

  • Consolidates admin functions like recoverToken
  • Reduces contract size by moving rarely used functions to library
  • Maintains same API and behavior
  • Uses custom errors for gas efficiency

Note: security-contact: team@quantillon.money

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

recoverToken

Recover tokens to treasury address

Emergency function to recover ERC20 tokens sent to the contract

Notes:

  • security: Requires admin role

  • validation: None required

  • state-changes: Transfers tokens from contract to treasury

  • events: Emits TokenRecovered event

  • errors: Throws NotAuthorized if caller lacks admin role

  • reentrancy: Not protected - library handles reentrancy

  • access: Restricted to admin role

  • oracle: Not applicable

function recoverToken(address contractInstance, address token, uint256 amount, address treasury, bytes32 adminRole)
    external;

Parameters

NameTypeDescription
contractInstanceaddressThe contract instance calling this function
tokenaddressAddress of the token to recover
amountuint256Amount of tokens to recover
treasuryaddressThe treasury address to send tokens to
adminRolebytes32The admin role required for this operation

CommonErrorLibrary

Git Source

Title: CommonErrorLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Common errors used across multiple contracts in Quantillon Protocol

Main characteristics:

  • Most frequently used errors across all contracts
  • Reduces contract size by importing only needed errors
  • Replaces require statements with custom errors for gas efficiency
  • Used by 15+ contracts

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Errors

InvalidAmount

error InvalidAmount();

ZeroAddress

error ZeroAddress();

InvalidAddress

error InvalidAddress();

InsufficientBalance

error InsufficientBalance();

NotAuthorized

error NotAuthorized();

ArrayLengthMismatch

error ArrayLengthMismatch();

BatchSizeTooLarge

error BatchSizeTooLarge();

EmptyArray

error EmptyArray();

InvalidTime

error InvalidTime();

AboveLimit

error AboveLimit();

WouldExceedLimit

error WouldExceedLimit();

ExcessiveSlippage

error ExcessiveSlippage();

ConfigValueTooHigh

error ConfigValueTooHigh();

ConfigValueTooLow

error ConfigValueTooLow();

NotAdmin

error NotAdmin();

InvalidAdmin

error InvalidAdmin();

InvalidTreasury

error InvalidTreasury();

InvalidToken

error InvalidToken();

InvalidOracle

error InvalidOracle();

InvalidVault

error InvalidVault();

AlreadyInitialized

error AlreadyInitialized();

NotInitialized

error NotInitialized();

NotActive

error NotActive();

BelowThreshold

error BelowThreshold();

NoChangeDetected

error NoChangeDetected();

DivisionByZero

error DivisionByZero();

PercentageTooHigh

error PercentageTooHigh();

InvalidParameter

error InvalidParameter();

InvalidCondition

error InvalidCondition();

ETHTransferFailed

error ETHTransferFailed();

NoETHToRecover

error NoETHToRecover();

CannotRecoverOwnToken

error CannotRecoverOwnToken();

EmergencyModeActive

error EmergencyModeActive();

HoldingPeriodNotMet

error HoldingPeriodNotMet();

InvalidPrice

error InvalidPrice();

InsufficientCollateralization

error InsufficientCollateralization();

TooManyPositions

error TooManyPositions();

PositionNotActive

error PositionNotActive();

LiquidationCooldown

error LiquidationCooldown();

InvalidRatio

error InvalidRatio();

NotGovernance

error NotGovernance();

NotEmergencyRole

error NotEmergencyRole();

NotLiquidatorRole

error NotLiquidatorRole();

NotVaultManager

error NotVaultManager();

NotYieldManager

error NotYieldManager();

InsufficientYield

error InsufficientYield();

InvalidShiftRange

error InvalidShiftRange();

YieldCalculationError

error YieldCalculationError();

VotingPeriodTooShort

error VotingPeriodTooShort();

VotingPeriodTooLong

error VotingPeriodTooLong();

VotingNotStarted

error VotingNotStarted();

VotingEnded

error VotingEnded();

AlreadyVoted

error AlreadyVoted();

NoVotingPower

error NoVotingPower();

VotingNotEnded

error VotingNotEnded();

ProposalAlreadyExecuted

error ProposalAlreadyExecuted();

ProposalCanceled

error ProposalCanceled();

ProposalFailed

error ProposalFailed();

QuorumNotMet

error QuorumNotMet();

ProposalAlreadyCanceled

error ProposalAlreadyCanceled();

ExecutionTimeNotReached

error ExecutionTimeNotReached();

LockTimeTooShort

error LockTimeTooShort();

LockTimeTooLong

error LockTimeTooLong();

RateLimitTooHigh

error RateLimitTooHigh();

InvalidOraclePrice

error InvalidOraclePrice();

YieldClaimFailed

error YieldClaimFailed();

InvalidThreshold

error InvalidThreshold();

NotWhitelisted

error NotWhitelisted();

InsufficientVotingPower

error InsufficientVotingPower();

CommonValidationLibrary

Git Source

Title: CommonValidationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Common validation functions used across multiple contracts

Main characteristics:

  • Consolidates common validation patterns
  • Reduces code duplication across contracts
  • Uses custom errors for gas efficiency
  • Maintains same validation logic

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

validateNonZeroAddress

Validates that an address is not zero

Checks if the provided address is the zero address and reverts with appropriate error. Uses string comparison which is gas-intensive but maintains backward compatibility. For new code, prefer using validateNonZeroAddressWithType() with AddressType enum.

Notes:

  • security: Pure; no state change

  • validation: Reverts if addr is zero

  • state-changes: None

  • events: None

  • errors: InvalidAdmin, InvalidTreasury, InvalidToken, InvalidOracle, InvalidVault, InvalidAddress

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateNonZeroAddress(address addr, string memory errorType) internal pure;

Parameters

NameTypeDescription
addraddressThe address to validate
errorTypestringThe type of address being validated (admin, treasury, token, oracle, vault)

validatePositiveAmount

Validates that an amount is positive

Reverts with InvalidAmount if amount is zero

Notes:

  • security: Pure; no state change

  • validation: Reverts if amount is zero

  • state-changes: None

  • events: None

  • errors: InvalidAmount

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validatePositiveAmount(uint256 amount) internal pure;

Parameters

NameTypeDescription
amountuint256The amount to validate

validateMinAmount

Validates that an amount is above minimum threshold

Reverts with InsufficientBalance if amount is below minimum

Notes:

  • security: Pure; no state change

  • validation: Reverts if amount < minAmount

  • state-changes: None

  • events: None

  • errors: InsufficientBalance

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateMinAmount(uint256 amount, uint256 minAmount) internal pure;

Parameters

NameTypeDescription
amountuint256The amount to validate
minAmountuint256The minimum required amount

validateMaxAmount

Validates that an amount is below maximum threshold

Reverts with AboveLimit if amount exceeds maximum

Notes:

  • security: Pure; no state change

  • validation: Reverts if amount > maxAmount

  • state-changes: None

  • events: None

  • errors: AboveLimit

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateMaxAmount(uint256 amount, uint256 maxAmount) internal pure;

Parameters

NameTypeDescription
amountuint256The amount to validate
maxAmountuint256The maximum allowed amount

validatePercentage

Validates that a percentage is within valid range

Reverts with AboveLimit if percentage exceeds maximum

Notes:

  • security: Pure; no state change

  • validation: Reverts if percentage > maxPercentage

  • state-changes: None

  • events: None

  • errors: AboveLimit

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validatePercentage(uint256 percentage, uint256 maxPercentage) internal pure;

Parameters

NameTypeDescription
percentageuint256The percentage to validate (in basis points)
maxPercentageuint256The maximum allowed percentage (in basis points)

validateCondition

Validates that a boolean condition is true

Generic condition validator that throws specific errors based on error type

Notes:

  • security: Pure; no state change

  • validation: Reverts if condition is false

  • state-changes: None

  • events: None

  • errors: InvalidOracle, InsufficientCollateralization, NotAuthorized, InvalidCondition

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateCondition(bool condition, string memory errorType) internal pure;

Parameters

NameTypeDescription
conditionboolThe condition to validate
errorTypestringThe type of error to throw if condition is false

_keccak256Bytes

Internal keccak256 of string using inline assembly (gas-efficient)

function _keccak256Bytes(string memory s) private pure returns (bytes32);

validateCountLimit

Validates that a count is within limits

Reverts with TooManyPositions if count exceeds or equals maximum

Notes:

  • security: Pure; no state change

  • validation: Reverts if count >= maxCount

  • state-changes: None

  • events: None

  • errors: TooManyPositions

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateCountLimit(uint256 count, uint256 maxCount) internal pure;

Parameters

NameTypeDescription
countuint256The current count
maxCountuint256The maximum allowed count

validateSufficientBalance

Validates that a balance is sufficient

Reverts with InsufficientBalance if balance is below required amount

Notes:

  • security: Pure; no state change

  • validation: Reverts if balance < requiredAmount

  • state-changes: None

  • events: None

  • errors: InsufficientBalance

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateSufficientBalance(uint256 balance, uint256 requiredAmount) internal pure;

Parameters

NameTypeDescription
balanceuint256The current balance
requiredAmountuint256The required amount

validateTreasuryAddress

Validates treasury address is not zero address

Reverts with ZeroAddress if treasury is zero address

Notes:

  • security: Pure; no state change

  • validation: Reverts if treasury is zero

  • state-changes: None

  • events: None

  • errors: ZeroAddress

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateTreasuryAddress(address treasury) internal pure;

Parameters

NameTypeDescription
treasuryaddressThe treasury address to validate

IExecutionCollateralView

Git Source

Reference collateral read used by linked vault calculations.

Functions

getTotalUsdcAvailable

Read reference-accounted collateral available to the vault.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function getTotalUsdcAvailable() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256result Value returned by the read interface.

ExecutionPricingLibrary

Git Source

Title: ExecutionPricingLibrary

Linked vault integration for volume pricing, preserving reference accounting.

Functions

version

Linked library semantic version.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringresult Calculated result in the units described by this operation.

mint

Calculate and consume a mint quote, reverting below the user's floor.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Called by delegatecall from the guarded vault flow.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Called from the guarded vault flow.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function mint(IExecutionPricing module, uint256 input, uint256 feeRate, uint256 ref, uint256 minimum)
    external
    returns (uint256 fee, uint256 backing, uint256 q);

Parameters

NameTypeDescription
moduleIExecutionPricingConfigured pricing module, or zero before activation.
inputuint256Gross USDC input.
feeRateuint256Protocol fee fraction in 18 decimals.
refuint256Reference EUR/USD price in 18 decimals.
minimumuint256Minimum QEURO output in 18 decimals.

Returns

NameTypeDescription
feeuint256Protocol fee in USDC.
backinguint256Net reference backing in USDC.
quint256QEURO output.

redeem

Calculate and consume a normal redemption quote.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: No execution cost is charged twice; gross = net + fee + spread.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Called from the guarded vault flow.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function redeem(IExecutionPricing module, uint256 q, uint256 feeRate, uint256 ref, uint256 minimum)
    external
    returns (uint256 gross, uint256 net, uint256 fee);

Parameters

NameTypeDescription
moduleIExecutionPricingConfigured pricing module, or zero before activation.
quint256QEURO input in 18 decimals.
feeRateuint256Protocol fee fraction in 18 decimals.
refuint256Reference EUR/USD price in 18 decimals.
minimumuint256Minimum USDC output in 6 decimals.

Returns

NameTypeDescription
grossuint256Reference-valued collateral removed.
netuint256User payout after execution spread and protocol fee.
feeuint256Protocol fee in USDC.

validateConfiguration

Check a governance module transition without discarding pending exposure.

Read-only contract interface.

Notes:

  • security: The vault enforces governance and pause requirements before delegation.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function validateConfiguration(IExecutionPricing previous, address next)
    external
    view
    returns (bool signedExecution);

Parameters

NameTypeDescription
previousIExecutionPricingPrevious configured module.
nextaddressProposed module, or zero to deactivate.

Returns

NameTypeDescription
signedExecutionboolWhether the validated module requires signed settlement contexts.

routeFees

Route protocol fees independently of execution spreads.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Delegatecalled within the vault's guarded settlement flow.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Called from the guarded vault flow.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function routeFees(
    IERC20 token,
    uint256 fee,
    uint256 split,
    IHedgerPool hedger,
    address collector,
    string memory source
) external;

Parameters

NameTypeDescription
tokenIERC20USDC token.
feeuint256Protocol fee amount.
splituint256Hedger reward fraction in 18 decimals.
hedgerIHedgerPoolHedger reward pool.
collectoraddressProtocol fee collector.
sourcestringAccounting source tag.

enforceDeviation

Enforce the vault's existing reference-price deviation policy.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Preserves the 200 bps and one-block policy independently of execution pricing.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Called from the guarded vault flow.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function enforceDeviation(uint256 price, uint256 previous, uint256 lastBlock) external;

Parameters

NameTypeDescription
priceuint256Live reference price.
previousuint256Cached reference price.
lastBlockuint256Block of the previous cache update.

enforceCollateralization

Validate projected reference-valued collateralization.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Execution spread reserves are excluded by the caller.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function enforceCollateralization(uint256 collateral, uint256 supply, uint256 price, uint256 minimum)
    external
    pure;

Parameters

NameTypeDescription
collateraluint256Projected collateral in USDC units.
supplyuint256Projected QEURO supply.
priceuint256Reference price.
minimumuint256Minimum collateralization percentage scaled by 1e18.

collateralizationRatio

Compute the reference-valued collateralization ratio for the calling vault.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Reads collateral only after nonzero reference backing is established.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function collateralizationRatio(IERC20 token, uint256 price) public view returns (uint256 ratio);

Parameters

NameTypeDescription
tokenIERC20QEURO token used for total circulating supply.
priceuint256Reference USD per EUR price.

Returns

NameTypeDescription
ratiouint256Percentage scaled by 1e18, or zero for absent backing.

enforceYieldEligibility

Validates yield conversion independently of the public mint gate.

No dust-supply bootstrap exemption applies to yield conversion.

Notes:

  • security: Requires CR strictly above max(101%, critical).

  • validation: Requires initialized pricing and an active hedger.

  • state-changes: None.

  • events: None.

  • errors: NotInitialized, NoActiveHedgerLiquidity, InsufficientCollateralization.

  • reentrancy: Static reads only.

  • access: Linked vault library.

  • oracle: Uses the validated price supplied by the vault.

function enforceYieldEligibility(IERC20 token, IHedgerPool hedger, uint256 cached, uint256 price, uint256 critical)
    external
    view;

Parameters

NameTypeDescription
tokenIERC20QEURO token.
hedgerIHedgerPoolActive hedger pool.
cacheduint256Initialized cached price.
priceuint256Validated current price.
criticaluint256Liquidation threshold in percentage scaled by 1e18.

enforceMintEligibility

Enforce initialized pricing, active hedging and the live mint floor.

Read-only contract interface.

Notes:

  • security: Preserves the vault's bounded dust-supply bootstrap behavior.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function enforceMintEligibility(IERC20 token, IHedgerPool hedger, uint256 cached, uint256 price, uint256 minimum)
    external
    view;

Parameters

NameTypeDescription
tokenIERC20QEURO token.
hedgerIHedgerPoolConfigured hedger pool.
cacheduint256Previously initialized reference price.
priceuint256Live reference price.
minimumuint256Minimum collateralization percentage scaled by 1e18.

Events

ProtocolFeeRouted

event ProtocolFeeRouted(string sourceType, uint256 totalFee, uint256 hedgerReserveShare, uint256 collectorShare);

PriceDeviationDetected

event PriceDeviationDetected(
    uint256 currentPrice, uint256 lastValidPrice, uint256 deviationBps, uint256 blockNumber
);

FlashLoanProtectionLibrary

Git Source

Title: FlashLoanProtectionLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Library for protecting contracts against flash loan attacks

This library provides functions to detect and prevent flash loan attacks by monitoring balance changes during function execution.

Flash loan attacks can occur when:

  • An attacker borrows a large amount of tokens
  • Manipulates protocol state (e.g., governance votes, price oracles)
  • Repays the loan in the same transaction
  • Profits from the manipulated state

Protection mechanism:

  • Balance checks before and after function execution
  • Validation that balances don't decrease unexpectedly

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

validateBalanceChange

Validates that a balance change is within acceptable limits

This function validates that balances don't decrease beyond acceptable limits. Currently used by all contract modifiers to prevent flash loan attacks. A maxDecrease of 0 means no decrease is allowed (strict protection).

Notes:

  • security: Prevents flash loan attacks by validating balance changes

  • validation: Validates balance changes are within acceptable limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No custom errors thrown

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function validateBalanceChange(uint256 balanceBefore, uint256 balanceAfter, uint256 maxDecrease)
    internal
    pure
    returns (bool);

Parameters

NameTypeDescription
balanceBeforeuint256Balance before operation
balanceAfteruint256Balance after operation
maxDecreaseuint256Maximum allowed decrease in balance

Returns

NameTypeDescription
<none>boolbool True if balance change is acceptable

HedgerPoolAccountingLibrary

Git Source

Title: HedgerPoolAccountingLibrary

Existing pool accounting extracted to keep HedgerPool deployable.

Delegatecalled with explicit storage references; correction replay protection uses a dedicated hashed namespace.

Constants

LEGACY_CORRECTION_SLOT

bytes32 private constant LEGACY_CORRECTION_SLOT = keccak256("quantillon.storage.LegacyMarginCorrection.20260701")

LEGACY_CORRECTION_ID

bytes32 private constant LEGACY_CORRECTION_ID = keccak256("base:48054036:hedger-profit:388448")

LEGACY_POOL

address private constant LEGACY_POOL = 0xff5D7cE5c7671B2EA805Ee752B4f8eC9Ecf2975A

LEGACY_SAFE

address private constant LEGACY_SAFE = 0x1d7fF432a93d0085Fb69474c7E567f859829e6cd

LEGACY_CREDIT

uint256 private constant LEGACY_CREDIT = 388448

Functions

routeFee

Routes collected fees between the reward reserve and collector.

Reserve amounts remain in the calling pool.

Notes:

  • security: Caller validates the configured split and recipient.

  • validation: A zero fee is a no-op.

  • state-changes: Transfers the collector portion and updates allowance.

  • events: RewardReserveFunded and collector events.

  • errors: Propagates token and collector failures.

  • reentrancy: Calling pool holds its reentrancy guard.

  • access: Linked library.

  • oracle: None.

function routeFee(
    IERC20 usdc,
    address collector,
    uint256 split,
    address funder,
    uint256 fee,
    string memory sourceType
) external;

Parameters

NameTypeDescription
usdcIERC20Collateral token.
collectoraddressFee collector address.
splituint256Reserve fraction scaled by 1e18.
funderaddressAccount credited with funding the reserve.
feeuint256Collected fee in USDC units.
sourceTypestringCollector accounting category.

assignSingleHedger

Assigns the configured owner with the existing inactive-position restriction.

Extracted unchanged to preserve EIP-170 headroom for the correction entry point.

Notes:

  • security: Helper enforces the existing governance role.

  • validation: Nonzero recipient and no active position when replacing an owner.

  • state-changes: None; wrapper stores returned owner.

  • events: SingleHedgerRotationApplied.

  • errors: InvalidAddress, HedgerHasActivePosition.

  • reentrancy: No external calls.

  • access: Linked library only.

  • oracle: No oracle dependency.

function assignSingleHedger(HedgerPool.HedgePosition storage position, address next) external returns (address);

Parameters

NameTypeDescription
positionHedgerPool.HedgePositionFixed position one, used only to read its active flag.
nextaddressRequested owner.

Returns

NameTypeDescription
<none>addressConfigured owner after assignment.

correctLegacyMargin

Reclassifies exactly the verified historical residue as current Safe margin once.

No deposit, withdrawal, mint, cost-basis change or realized-PnL adjustment occurs. Exact surplus and opening-block checks reject drift or reuse for another position.

Notes:

  • security: Fixed chain/pool/owner/position and governance, pause and replay guards.

  • validation: Verifies global totals, supply/backing dust and exact existing surplus.

  • state-changes: Updates margin, position size and namespaced one-time marker.

  • events: LegacyMarginCorrected.

  • errors: LegacyCorrectionUnauthorized, LegacyCorrectionStateMismatch, LegacyCorrectionAlreadyApplied.

  • reentrancy: Pool wrapper is nonReentrant; external calls are static reads.

  • access: Linked library invoked by the fixed Base pool through delegatecall.

  • oracle: Independent of oracle price and cached valuation.

function correctLegacyMargin(HedgerPool.HedgePosition storage position)
    external
    returns (uint256 nextTotalMargin, uint256 nextTotalExposure);

Parameters

NameTypeDescription
positionHedgerPool.HedgePositionThe pool's fixed active position one.

Returns

NameTypeDescription
nextTotalMarginuint256Global margin after correction.
nextTotalExposureuint256Global nominal exposure after correction.

validateClosure

Preserves the pool's existing restriction on closing while users remain exposed.

Extracted unchanged; bounded QEURO dust is treated as an empty supply.

Notes:

  • security: Read-only closure guard.

  • validation: Requires sufficient remaining hedger margin when QEURO is outstanding.

  • state-changes: None.

  • events: None.

  • errors: PositionClosureRestricted.

  • reentrancy: External static reads only.

  • access: Linked library invoked by HedgerPool.

  • oracle: No price dependency.

function validateClosure(IQuantillonVault vault, uint256 positionMargin) external view;

Parameters

NameTypeDescription
vaultIQuantillonVaultConfigured vault.
positionMarginuint256Closing position's recorded margin.

configure

Validates and applies the existing risk and fee configuration.

Scalar settings outside CoreParams remain assigned by the pool.

Notes:

  • security: Pool wrappers enforce caller authority and storage references.

  • validation: Uses the pool's existing validation rules.

  • state-changes: Updates only the explicitly supplied accounting storage.

  • events: None.

  • errors: Propagates accounting, validation and trusted integration errors.

  • reentrancy: State-changing pool wrappers are nonReentrant except governance configuration.

  • access: Linked library invoked by HedgerPool through delegatecall.

  • oracle: No oracle lookup; prices, where present, are supplied by the caller.

function configure(
    HedgerPool.CoreParams storage params,
    HedgerPool.HedgerRiskConfig calldata cfg,
    HedgerPool.HedgePosition storage position
) external;

Parameters

NameTypeDescription
paramsHedgerPool.CoreParamsPool core parameters in storage.
cfgHedgerPool.HedgerRiskConfigRequested complete risk and fee configuration.
positionHedgerPool.HedgePositionActive position used to bound the margin-ratio setting.

effectiveCollateral

Values the active position using remaining cost and the caller's price.

Floors negative effective collateral at zero; realized history is already in margin.

Notes:

  • security: Read-only helper.

  • validation: No input validation required unless described above.

  • state-changes: None.

  • events: None.

  • errors: None beyond checked arithmetic.

  • reentrancy: No state-changing external calls.

  • access: Linked library helper.

  • oracle: No oracle lookup.

function effectiveCollateral(HedgerPool.HedgePosition storage position, uint256 price)
    external
    view
    returns (uint256);

Parameters

NameTypeDescription
positionHedgerPool.HedgePositionActive position storage.
priceuint256EUR/USD price with 18 decimals.

Returns

NameTypeDescription
<none>uint256collateral Effective USDC collateral, floored at zero.

version

Reports the initial library release.

Uses no additional sequential storage slots.

Notes:

  • security: Read-only helper.

  • validation: No input validation required unless described above.

  • state-changes: None.

  • events: None.

  • errors: None beyond checked arithmetic.

  • reentrancy: No state-changing external calls.

  • access: Linked library helper.

  • oracle: No oracle lookup.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringrelease Semantic version string.

checkpoint

Books interest earned up to the current exposure change.

Checkpointing before every exposure mutation prevents a later, larger exposure from being applied retroactively to an earlier accrual period.

Notes:

  • security: Uses only explicitly supplied storage and accounting inputs.

  • validation: Rejects reward overflow through the shared error library.

  • state-changes: Updates the hedger's pending reward and accrual clock.

  • events: None.

  • errors: RewardOverflow on uint128 overflow.

  • reentrancy: No external calls.

  • access: Linked library invoked by HedgerPool.

  • oracle: No oracle dependency.

function checkpoint(
    HedgerPool.HedgerRewardState storage rewardState,
    mapping(address => uint256) storage rewardTimes,
    HedgerPool.CoreParams storage params,
    uint256 totalExposure,
    uint256 currentTime,
    uint256 maxRewardPeriod,
    address hedger
) external returns (uint256 pendingRewards);

Parameters

NameTypeDescription
rewardStateHedgerPool.HedgerRewardStateHedger reward state.
rewardTimesmapping(address => uint256)Per-hedger accrual clocks.
paramsHedgerPool.CoreParamsPool interest-rate configuration.
totalExposureuint256Exposure that was active during the elapsed period.
currentTimeuint256Canonical protocol time.
maxRewardPerioduint256Maximum accrual duration.
hedgeraddressHedger whose clock is being checkpointed.

Returns

NameTypeDescription
pendingRewardsuint256Updated pending interest reward.

claim

Accrues interest into withdrawal escrow and claims external yield.

Preserves the pool's legacy-clock migration, narrowing casts and pull settlement.

Notes:

  • security: Pool wrappers enforce caller authority and storage references.

  • validation: Uses the pool's existing validation rules.

  • state-changes: Updates only the explicitly supplied accounting storage.

  • events: None.

  • errors: Propagates accounting, validation and trusted integration errors.

  • reentrancy: State-changing pool wrappers are nonReentrant except governance configuration.

  • access: Linked library invoked by HedgerPool through delegatecall.

  • oracle: No oracle lookup; prices, where present, are supplied by the caller.

function claim(
    HedgerPool.HedgerRewardState storage rewardState,
    mapping(address => uint256) storage rewardTimes,
    mapping(address => uint256) storage pendingWithdrawals,
    HedgerPool.CoreParams storage params,
    uint256 totalExposure,
    uint256 currentTime,
    uint256 maxRewardPeriod,
    IYieldShift yieldShift
) external returns (uint256 interestDifferential, uint256 yieldShiftRewards, uint256 totalRewards);

Parameters

NameTypeDescription
rewardStateHedgerPool.HedgerRewardStateCurrent hedger reward state.
rewardTimesmapping(address => uint256)Per-hedger accrual clocks.
pendingWithdrawalsmapping(address => uint256)Per-hedger withdrawal escrow.
paramsHedgerPool.CoreParamsPool interest rate configuration.
totalExposureuint256Pool notional exposure.
currentTimeuint256Canonical protocol time.
maxRewardPerioduint256Maximum accrual duration.
yieldShiftIYieldShiftTrusted yield distributor.

Returns

NameTypeDescription
interestDifferentialuint256Interest queued for withdrawal.
yieldShiftRewardsuint256Yield paid by YieldShift.
totalRewardsuint256Sum of both reward sources.

withdraw

Pays the caller's funded escrow balance to their chosen recipient.

Leaves any unfunded remainder available for a later withdrawal.

Notes:

  • security: Pool wrappers enforce caller authority and storage references.

  • validation: Uses the pool's existing validation rules.

  • state-changes: Reduces caller escrow by funded amount and transfers USDC.

  • events: None.

  • errors: Propagates accounting, validation and trusted integration errors.

  • reentrancy: Invoked from the nonReentrant withdrawal wrapper.

  • access: Linked library invoked by HedgerPool through delegatecall.

  • oracle: No oracle lookup; prices, where present, are supplied by the caller.

function withdraw(mapping(address => uint256) storage pendingWithdrawals, IERC20 usdc, address recipient) external;

Parameters

NameTypeDescription
pendingWithdrawalsmapping(address => uint256)Per-hedger withdrawal escrow.
usdcIERC20Pool collateral token.
recipientaddressCaller-selected payout recipient.

applyMarginTransition

Applies realized profit or loss to margin and notional exposure.

Keeps aggregate exposure aligned with the resulting position size.

Notes:

  • security: Caller checkpoints rewards before changing exposure.

  • validation: Shared math validates position bounds.

  • state-changes: Updates position margin and size.

  • events: None.

  • errors: Propagates checked arithmetic errors.

  • reentrancy: No external state-changing calls.

  • access: Linked library.

  • oracle: Caller supplies settled profit or loss.

function applyMarginTransition(
    HedgerPool.HedgePosition storage pos,
    uint256 totalMargin,
    uint256 totalExposure,
    int256 realizedDelta
) external returns (uint256 nextMargin, uint256 nextExposure);

Parameters

NameTypeDescription
posHedgerPool.HedgePositionPosition to update.
totalMarginuint256Aggregate margin before the transition.
totalExposureuint256Aggregate exposure before the transition.
realizedDeltaint256Realized USDC profit or loss.

Returns

NameTypeDescription
nextMarginuint256Aggregate margin after settlement.
nextExposureuint256Aggregate exposure after settlement.

Events

LegacyMarginCorrected

event LegacyMarginCorrected(bytes32 indexed correctionId, address indexed hedger, uint256 amount);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

RewardReserveFunded

event RewardReserveFunded(address indexed funder, uint256 amount);

Errors

LegacyCorrectionUnauthorized

error LegacyCorrectionUnauthorized();

LegacyCorrectionStateMismatch

error LegacyCorrectionStateMismatch();

LegacyCorrectionAlreadyApplied

error LegacyCorrectionAlreadyApplied();

HedgerPoolErrorLibrary

Git Source

Title: HedgerPoolErrorLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

HedgerPool-specific errors for Quantillon Protocol

Main characteristics:

  • Errors specific to HedgerPool operations
  • Trading position management errors
  • Liquidation system errors
  • Margin and leverage validation errors

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Errors

FlashLoanAttackDetected

error FlashLoanAttackDetected();

InvalidPosition

error InvalidPosition();

InvalidHedger

error InvalidHedger();

OnlyVault

error OnlyVault();

RewardOverflow

error RewardOverflow();

InsufficientMargin

error InsufficientMargin();

MarginExceedsMaximum

error MarginExceedsMaximum();

PositionSizeExceedsMaximum

error PositionSizeExceedsMaximum();

EntryPriceExceedsMaximum

error EntryPriceExceedsMaximum();

LeverageExceedsMaximum

error LeverageExceedsMaximum();

TimestampOverflow

error TimestampOverflow();

TotalMarginExceedsMaximum

error TotalMarginExceedsMaximum();

TotalExposureExceedsMaximum

error TotalExposureExceedsMaximum();

NewMarginExceedsMaximum

error NewMarginExceedsMaximum();

InvalidLeverage

error InvalidLeverage();

LeverageTooHigh

error LeverageTooHigh();

MarginRatioTooLow

error MarginRatioTooLow();

MarginRatioTooHigh

error MarginRatioTooHigh();

PositionOwnerMismatch

error PositionOwnerMismatch();

PositionClosureRestricted

error PositionClosureRestricted();

InsufficientHedgerCapacity

error InsufficientHedgerCapacity();

NoActiveHedgerLiquidity

error NoActiveHedgerLiquidity();

HedgerHasActivePosition

error HedgerHasActivePosition();

MinHoldPeriodNotElapsed

error MinHoldPeriodNotElapsed();

HedgerPoolLogicLibrary

Git Source

Title: HedgerPoolLogicLibrary

Author: Quantillon Labs

Logic functions for HedgerPool to reduce contract size

Filled volume is the original USDC cost of the remaining QEURO backing. Unrealized P&L = filledVolume - qeuroBacked * currentPrice / 1e30. Effective margin = margin + unrealized P&L. Realized P&L is already in margin and never enters remaining-exposure valuation. Legacy argument positions are retained in public library signatures for ABI compatibility.

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

validateAndCalculatePositionParams

Validates position parameters and calculates derived values

Validates all position constraints and calculates fee, margin, and position size

Notes:

  • security: Validates all position constraints and limits

  • validation: Ensures amounts, leverage, and ratios are within limits

  • state-changes: None (pure function)

  • events: None

  • errors: Throws various validation errors if constraints not met

  • reentrancy: Not applicable - pure function

  • access: External pure function

  • oracle: Uses provided eurUsdPrice parameter

function validateAndCalculatePositionParams(PositionValidationInput calldata params)
    external
    pure
    returns (uint256 fee, uint256 netMargin, uint256 positionSize, uint256 marginRatio);

Parameters

NameTypeDescription
paramsPositionValidationInputPacked position validation inputs

Returns

NameTypeDescription
feeuint256Calculated entry fee
netMarginuint256Net margin after fee deduction
positionSizeuint256Calculated position size
marginRatiouint256Calculated margin ratio

calculatePnL

Calculates TOTAL unrealized P&L for a hedge position (mark-to-market)

Formula: TotalUnrealizedP&L = FilledVolume - (QEUROBacked × OraclePrice / 1e30) Hedgers are SHORT EUR (they owe QEURO to users). When price rises, they lose.

  • Price UP → qeuroValueInUSDC increases → P&L becomes more negative → hedger loses
  • Price DOWN → qeuroValueInUSDC decreases → P&L becomes more positive → hedger profits This returns the TOTAL unrealized P&L for the current position state. Historical realized P&L is already included in margin and must not be subtracted.

Notes:

  • security: No security validations required for pure function

  • validation: Returns zero for a zero price; callers validate oracle prices.

  • state-changes: None (pure function)

  • events: None (pure function)

  • errors: None (returns 0 for edge cases)

  • reentrancy: Not applicable (pure function)

  • access: Internal library function

  • oracle: Uses provided currentPrice parameter (must be fresh oracle data)

function calculatePnL(uint256 filledVolume, uint256 qeuroBacked, uint256 currentPrice)
    internal
    pure
    returns (int256);

Parameters

NameTypeDescription
filledVolumeuint256Size of the filled position in USDC (6 decimals)
qeuroBackeduint256Exact QEURO amount backed by this position (18 decimals)
currentPriceuint256Current EUR/USD oracle price (18 decimals)

Returns

NameTypeDescription
<none>int256Profit (positive) or loss (negative) amount in USDC (6 decimals)

calculateCollateralCapacity

Calculates collateral-based capacity for a position

Returns how much additional USDC exposure a position can absorb Formula breakdown:

  1. totalUnrealizedPnL = calculatePnL(filledVolume, qeuroBacked, currentPrice)
  2. Realized P&L is informational history already included in margin.
  3. effectiveMargin = margin + totalUnrealizedPnL
  4. requiredMargin = (qeuroBacked × currentPrice / 1e30) × minMarginRatio / 10000
  5. availableCollateral = effectiveMargin - requiredMargin
  6. capacity = availableCollateral × 10000 / minMarginRatio

Notes:

  • security: No security validations required for pure function

  • validation: Validates currentPrice > 0 and minMarginRatio > 0

  • state-changes: None (pure function)

  • events: None (pure function)

  • errors: None (returns 0 for invalid inputs)

  • reentrancy: Not applicable (pure function)

  • access: Internal library function

  • oracle: Uses provided currentPrice parameter (must be fresh oracle data)

function calculateCollateralCapacity(
    uint256 margin,
    uint256 filledVolume,
    uint256,
    /* entryPrice */
    uint256 currentPrice,
    uint256 minMarginRatio,
    int128,
    /* realizedPnL */
    uint128 qeuroBacked
) internal pure returns (uint256);

Parameters

NameTypeDescription
marginuint256Position margin in USDC (6 decimals)
filledVolumeuint256Current filled volume in USDC (6 decimals)
<none>uint256
currentPriceuint256Current EUR/USD oracle price (18 decimals)
minMarginRatiouint256Minimum margin ratio in basis points (e.g., 500 = 5%)
<none>int128
qeuroBackeduint128Exact QEURO amount backed by this position (18 decimals)

Returns

NameTypeDescription
<none>uint256capacity Additional USDC exposure the position can absorb (6 decimals)

isPositionLiquidatable

Determines if a position is eligible for liquidation

Checks if position margin ratio falls below the liquidation threshold Formula breakdown:

  1. totalUnrealizedPnL = calculatePnL(filledVolume, qeuroBacked, currentPrice)
  2. Realized P&L is informational history already included in margin.
  3. effectiveMargin = margin + totalUnrealizedPnL
  4. qeuroValueInUSDC = qeuroBacked × currentPrice / 1e30
  5. marginRatio = effectiveMargin × 10000 / qeuroValueInUSDC
  6. liquidatable = marginRatio < liquidationThreshold

Notes:

  • security: No security validations required for pure function

  • validation: Validates currentPrice > 0 and liquidationThreshold > 0

  • state-changes: None (pure function)

  • events: None (pure function)

  • errors: None (returns false for invalid inputs)

  • reentrancy: Not applicable (pure function)

  • access: Internal library function

  • oracle: Uses provided currentPrice parameter (must be fresh oracle data)

function isPositionLiquidatable(
    uint256 margin,
    uint256 filledVolume,
    uint256,
    /* entryPrice */
    uint256 currentPrice,
    uint256 liquidationThreshold,
    uint128 qeuroBacked,
    int128 /* realizedPnL */
) external pure returns (bool);

Parameters

NameTypeDescription
marginuint256Current margin amount for the position (6 decimals USDC)
filledVolumeuint256Filled size of the position in USDC (6 decimals)
<none>uint256
currentPriceuint256Current EUR/USD oracle price (18 decimals)
liquidationThresholduint256Minimum margin ratio in basis points (e.g., 500 = 5%)
qeuroBackeduint128Exact QEURO amount backed by this position (18 decimals)
<none>int128

Returns

NameTypeDescription
<none>boolTrue if position margin ratio is below threshold, false otherwise

calculateRewardUpdate

Calculates reward updates for hedgers based on interest rate differentials

Computes new pending rewards based on time elapsed and interest rates

Notes:

  • security: No security validations required for pure function

  • validation: None required for pure function

  • state-changes: None (pure function)

  • events: None

  • errors: None

  • reentrancy: Not applicable - pure function

  • access: External pure function

  • oracle: Not applicable

function calculateRewardUpdate(
    uint256 totalExposure,
    uint256 eurInterestRate,
    uint256 usdInterestRate,
    uint256 lastRewardTime,
    uint256 currentTime,
    uint256 maxRewardPeriod,
    uint256 currentPendingRewards
) external pure returns (uint256 newPendingRewards, uint256 newLastRewardTime);

Parameters

NameTypeDescription
totalExposureuint256Total exposure for the hedger position
eurInterestRateuint256EUR interest rate in basis points
usdInterestRateuint256USD interest rate in basis points
lastRewardTimeuint256Timestamp of last reward calculation
currentTimeuint256Current timestamp
maxRewardPerioduint256Maximum reward period in seconds
currentPendingRewardsuint256Current pending rewards amount

Returns

NameTypeDescription
newPendingRewardsuint256Updated pending rewards amount
newLastRewardTimeuint256Updated last reward timestamp

validateMarginOperation

Validates margin operations and calculates new margin values

Validates margin addition/removal and calculates resulting margin ratio

Notes:

  • security: Validates margin constraints and limits

  • validation: Ensures margin operations are within limits

  • state-changes: None (pure function)

  • events: None

  • errors: Throws InsufficientMargin or validation errors

  • reentrancy: Not applicable - pure function

  • access: External pure function

  • oracle: Not applicable

function validateMarginOperation(
    uint256 currentMargin,
    uint256 amount,
    bool isAddition,
    uint256 minMarginRatio,
    uint256 positionSize,
    uint256 maxMargin
) external pure returns (uint256 newMargin, uint256 newMarginRatio);

Parameters

NameTypeDescription
currentMarginuint256Current margin amount for the position
amountuint256Amount of margin to add or remove
isAdditionboolTrue if adding margin, false if removing
minMarginRatiouint256Minimum margin ratio in basis points
positionSizeuint256Size of the position in USDC
maxMarginuint256Maximum margin per position

Returns

NameTypeDescription
newMarginuint256New margin amount after operation
newMarginRatiouint256New margin ratio after operation

Structs

PositionValidationInput

struct PositionValidationInput {
    uint256 usdcAmount;
    uint256 leverage;
    uint256 eurUsdPrice;
    uint256 entryFee;
    uint256 minMarginRatio;
    uint256 maxMarginRatio;
    uint256 maxLeverage;
    uint256 maxMargin;
    uint256 maxPositionSize;
    uint256 maxEntryPrice;
    uint256 maxLeverageValue;
    uint256 currentTime;
}

HedgerPoolMigrationLibrary

Git Source

Title: HedgerPoolMigrationLibrary

Three-party ownership transfer preserving the live single-hedger position.

Linked library operating in the pool's storage through delegatecall. Proposal state occupies a dedicated hashed namespace; existing HedgerPool slots are unchanged.

Constants

STORAGE_SLOT

bytes32 private constant STORAGE_SLOT = keccak256("quantillon.storage.HedgerMigration.v1")

Functions

version

Reports the first release of the migration library.

Uses no additional sequential storage slots.

Notes:

  • security: Read-only helper.

  • validation: No input validation required unless described above.

  • state-changes: None.

  • events: None.

  • errors: None beyond checked arithmetic.

  • reentrancy: No state-changing external calls.

  • access: Linked library helper.

  • oracle: No oracle lookup.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringrelease Semantic version string.

proposal

Returns the current migration proposal, or an empty proposal after completion/cancellation.

Uses no additional sequential storage slots.

Notes:

  • security: Read-only helper.

  • validation: No input validation required unless described above.

  • state-changes: None.

  • events: None.

  • errors: None beyond checked arithmetic.

  • reentrancy: No state-changing external calls.

  • access: Linked library helper.

  • oracle: No oracle lookup.

function proposal() external view returns (Proposal memory);

Returns

NameTypeDescription
<none>Proposalpending Current proposal or a zeroed struct.

manage

Proposes, accepts, executes or cancels a transfer using the caller's distinct authority.

Moves pool rewards and their accrual timestamp; external YieldShift entitlements remain with their original beneficiary and remain directly claimable at YieldShift.

Notes:

  • security: Enforces owner proposal, recipient acceptance and paused governance execution.

  • validation: Binds chain, pool, nonce, parties, expiry and position; rejects dirty recipients.

  • state-changes: Changes proposal state or transfers ownership, rewards, clocks and escrow atomically.

  • events: HedgerMigrationProposed, HedgerMigrationAccepted, HedgerMigrationCancelled, HedgerMigrationExecuted, SingleHedgerRotationApplied.

  • errors: MigrationUnauthorized, InvalidMigration, MigrationExpired, MigrationNotAccepted, RecipientHasHedgerState, MigrationRequiresPause.

  • reentrancy: Called from nonReentrant pool wrapper; no external calls.

  • access: Linked library invoked by HedgerPool through delegatecall.

  • oracle: No oracle lookup; prices, where present, are supplied by the caller.

function manage(
    Request calldata request,
    address singleHedger,
    bool governance,
    bool paused,
    HedgerPool.HedgePosition storage position,
    mapping(address => HedgerPool.HedgerRewardState) storage rewards,
    mapping(address => uint256) storage activePositions,
    mapping(address => uint256) storage rewardTimes,
    mapping(address => uint256) storage pendingWithdrawals
) external returns (address);

Parameters

NameTypeDescription
requestRequestAction and exact proposal fields.
singleHedgeraddressCurrent configured hedger.
governanceboolWhether caller holds governance role.
pausedboolWhether the pool is paused.
positionHedgerPool.HedgePositionActive single position storage.
rewardsmapping(address => HedgerPool.HedgerRewardState)Per-hedger reward state.
activePositionsmapping(address => uint256)Per-hedger active position IDs.
rewardTimesmapping(address => uint256)Per-hedger accrual clocks.
pendingWithdrawalsmapping(address => uint256)Per-hedger withdrawal escrow.

Returns

NameTypeDescription
<none>addresshedger Configured hedger after this action.

invalidate

Invalidates consent whenever the active position closes, including same-block reopenings.

Called by the pool's common position finalization path.

Notes:

  • security: Revokes prior consent when a position closes.

  • validation: No-op without a pending proposal.

  • state-changes: Deletes the current proposal, preserving the nonce.

  • events: HedgerMigrationCancelled when a proposal existed.

  • errors: None.

  • reentrancy: No external calls.

  • access: Linked library invoked by HedgerPool through delegatecall.

  • oracle: No oracle lookup; prices, where present, are supplied by the caller.

function invalidate() external;

_state

Returns the dedicated migration storage namespace.

Uses no additional sequential storage slots.

Notes:

  • security: Read-only helper.

  • validation: No input validation required unless described above.

  • state-changes: None.

  • events: None.

  • errors: None beyond checked arithmetic.

  • reentrancy: No state-changing external calls.

  • access: Linked library helper.

  • oracle: No oracle lookup.

function _state() private pure returns (State storage state);

Returns

NameTypeDescription
stateStateNamespaced migration state storage pointer.

Events

HedgerMigrationProposed

event HedgerMigrationProposed(
    bytes32 indexed proposalId, address indexed previousHedger, address indexed newHedger, uint64 expiresAt
);

HedgerMigrationAccepted

event HedgerMigrationAccepted(bytes32 indexed proposalId);

HedgerMigrationCancelled

event HedgerMigrationCancelled(bytes32 indexed proposalId);

HedgerMigrationExecuted

event HedgerMigrationExecuted(
    bytes32 indexed proposalId, address indexed previousHedger, address indexed newHedger
);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

Errors

MigrationUnauthorized

error MigrationUnauthorized();

InvalidMigration

error InvalidMigration();

MigrationExpired

error MigrationExpired();

MigrationNotAccepted

error MigrationNotAccepted();

RecipientHasHedgerState

error RecipientHasHedgerState();

MigrationRequiresPause

error MigrationRequiresPause();

Structs

Request

struct Request {
    Action action;
    address newHedger;
    uint64 expiresAt;
    bytes32 proposalId;
}

Proposal

struct Proposal {
    bytes32 id;
    address previousHedger;
    address newHedger;
    uint64 expiresAt;
    uint64 openBlock;
    bool accepted;
}

State

struct State {
    uint256 nonce;
    Proposal proposal;
}

Enums

Action

enum Action {
    Propose,
    Accept,
    Execute,
    Cancel
}

HedgerPoolRedeemMathLibrary

Git Source

Title: HedgerPoolRedeemMathLibrary

Externalized math helpers for redemption and realized PnL transitions

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

calculateRedeemPnL

Computes realized PnL delta for a redemption share.

Releases qeuroAmount / currentQeuroBacked of the original cost, rounded down, and subtracts the redemption payout, also rounded down to USDC units. The final redemption releases all remaining cost. The last argument is kept for ABI compatibility; historical realized P&L never changes this delta.

Notes:

  • security: Pure math helper; no direct security impact.

  • validation: Assumes currentQeuroBacked > 0 and qeuroAmount <= currentQeuroBacked are enforced by the caller.

  • state-changes: None – pure function.

  • events: None.

  • errors: None – callers must validate inputs.

  • reentrancy: Not applicable – pure function.

  • access: Library function; callable from HedgerPool only.

  • oracle: Expects price to be validated by caller using protocol oracle guards.

function calculateRedeemPnL(
    uint256 currentQeuroBacked,
    uint256 filledBefore,
    uint256 price,
    uint256 qeuroAmount,
    int128 /* previousRealizedPnL */
) external pure returns (int256 realizedDelta);

Parameters

NameTypeDescription
currentQeuroBackeduint256Total QEURO amount currently backed by the position.
filledBeforeuint256Total filled USDC notionals before redemption.
priceuint256Current EUR/USD price scaled as in VaultMath.mulDiv context (1e30 factor).
qeuroAmountuint256QEURO amount being redeemed (share of the position).
<none>int128

Returns

NameTypeDescription
realizedDeltaint256Signed realized PnL delta attributable to this redemption.

computeMarginTransition

Computes margin/position totals after applying realized PnL.

Updates per-position and global margin figures after realizing realizedDelta. Handles both profit and loss cases, including full margin wipe-out. Caps nextMargin and nextPositionSize to uint96 max to stay within packing limits.

Notes:

  • security: Pure math helper; callers must ensure values fit within business invariants.

  • validation: Assumes currentMargin and totalMarginBefore are consistent and that leverage is a sane protocol value; overflow is bounded by explicit caps.

  • state-changes: None – pure function, returns MarginTransition for caller to persist.

  • events: None.

  • errors: None – callers must handle invalid inputs.

  • reentrancy: Not applicable – pure function.

  • access: Library function; intended for HedgerPool internal use.

  • oracle: No direct oracle dependency – uses already-priced PnL delta.

function computeMarginTransition(
    uint256 totalMarginBefore,
    uint256 currentMargin,
    uint256 leverage,
    int256 realizedDelta
) external pure returns (MarginTransition memory t);

Parameters

NameTypeDescription
totalMarginBeforeuint256Global total margin across all positions before realization.
currentMarginuint256Margin currently allocated to the position being updated.
leverageuint256Position leverage used to recompute notional size from margin.
realizedDeltaint256Signed realized PnL amount to apply to this position.

Returns

NameTypeDescription
tMarginTransitionStruct encoding new margin, position size, ratio and flags describing outcome.

Structs

MarginTransition

struct MarginTransition {
    uint256 totalMarginAfter;
    uint256 nextMargin;
    uint256 nextPositionSize;
    uint256 deltaAmount;
    uint256 newMarginRatio;
    bool isProfit;
    bool marginWiped;
}

HedgerPoolValidationLibrary

Git Source

Title: HedgerPoolValidationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

HedgerPool-specific validation functions for Quantillon Protocol

Main characteristics:

  • Validation functions specific to HedgerPool operations
  • Trading position management validations
  • Liquidation system validations
  • Margin and leverage validation functions

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

validateLeverage

Validates leverage parameters for trading positions

Ensures leverage is within acceptable bounds (> 0 and <= max)

Notes:

  • security: Prevents excessive leverage that could cause system instability

  • validation: Ensures leverage is within acceptable risk bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidLeverage or LeverageTooHigh based on validation

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateLeverage(uint256 leverage, uint256 maxLeverage) internal pure;

Parameters

NameTypeDescription
leverageuint256The leverage multiplier to validate
maxLeverageuint256The maximum allowed leverage

validateMarginRatio

Validates margin ratio to ensure sufficient collateralization

Prevents positions from being under-collateralized

Notes:

  • security: Prevents under-collateralized positions that could cause liquidations

  • validation: Ensures sufficient margin for position safety

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws MarginRatioTooLow if ratio is below minimum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateMarginRatio(uint256 marginRatio, uint256 minRatio) internal pure;

Parameters

NameTypeDescription
marginRatiouint256The current margin ratio to validate
minRatiouint256The minimum required margin ratio

validateMaxMarginRatio

Validates margin ratio against maximum limit to prevent excessive collateralization

Prevents positions from being over-collateralized (leverage too low)

Notes:

  • security: Prevents over-collateralization that could reduce capital efficiency

  • validation: Ensures margin ratio stays within acceptable bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws MarginRatioTooHigh if ratio exceeds maximum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateMaxMarginRatio(uint256 marginRatio, uint256 maxRatio) internal pure;

Parameters

NameTypeDescription
marginRatiouint256The current margin ratio to validate
maxRatiouint256The maximum allowed margin ratio

validatePositionActive

Validates that a position is active before operations

Prevents operations on closed or invalid positions

Notes:

  • security: Prevents operations on inactive positions

  • validation: Ensures position is active before modifications

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws PositionNotActive if position is inactive

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validatePositionActive(bool isActive) internal pure;

Parameters

NameTypeDescription
isActiveboolThe position's active status

validatePositionOwner

Validates position ownership before allowing operations

Security check to ensure only position owner can modify it

Notes:

  • security: Prevents unauthorized position modifications

  • validation: Ensures only position owner can modify position

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws PositionOwnerMismatch if caller is not owner

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validatePositionOwner(address owner, address caller) internal pure;

Parameters

NameTypeDescription
owneraddressThe position owner's address
calleraddressThe address attempting the operation

validatePositionParams

Validates all position parameters against maximum limits

Ensures all position parameters are within acceptable bounds

Notes:

  • security: Prevents position parameters that could destabilize system

  • validation: Ensures all position parameters are within limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws specific errors for each parameter that exceeds limits

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validatePositionParams(
    uint256 netMargin,
    uint256 positionSize,
    uint256 eurUsdPrice,
    uint256 leverage,
    uint256 maxMargin,
    uint256 maxPositionSize,
    uint256 maxEntryPrice,
    uint256 maxLeverage
) internal pure;

Parameters

NameTypeDescription
netMarginuint256The net margin amount after fees
positionSizeuint256The size of the position
eurUsdPriceuint256The EUR/USD entry price
leverageuint256The leverage multiplier
maxMarginuint256Maximum allowed margin
maxPositionSizeuint256Maximum allowed position size
maxEntryPriceuint256Maximum allowed entry price
maxLeverageuint256Maximum allowed leverage

validateTotals

Validates total margin and exposure limits

Ensures combined totals don't exceed system-wide limits

Notes:

  • security: Prevents system-wide limits from being exceeded

  • validation: Ensures combined totals stay within system limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws TotalMarginExceedsMaximum or TotalExposureExceedsMaximum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateTotals(
    uint256 currentMargin,
    uint256 currentExposure,
    uint256 additionalMargin,
    uint256 additionalExposure,
    uint256 maxTotalMargin,
    uint256 maxTotalExposure
) internal pure;

Parameters

NameTypeDescription
currentMarginuint256Current total margin
currentExposureuint256Current total exposure
additionalMarginuint256Additional margin being added
additionalExposureuint256Additional exposure being added
maxTotalMarginuint256Maximum allowed total margin
maxTotalExposureuint256Maximum allowed total exposure

validateTimestamp

Validates timestamp fits in uint32 for storage optimization

Prevents timestamp overflow when casting to uint32

Notes:

  • security: Prevents timestamp overflow that could cause data corruption

  • validation: Ensures timestamp fits within uint32 bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws TimestampOverflow if timestamp exceeds uint32 max

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateTimestamp(uint256 timestamp) internal pure;

Parameters

NameTypeDescription
timestampuint256The timestamp to validate

validateNewMargin

Validates new margin amount against maximum limit

Ensures margin additions don't exceed individual position limits

Notes:

  • security: Prevents margin additions that exceed position limits

  • validation: Ensures new margin stays within position limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws NewMarginExceedsMaximum if new margin exceeds limit

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateNewMargin(uint256 newMargin, uint256 maxMargin) internal pure;

Parameters

NameTypeDescription
newMarginuint256The new total margin amount
maxMarginuint256Maximum allowed margin per position

validateFee

Validates fee amount against maximum allowed fee

Ensures fees don't exceed protocol limits (typically in basis points)

Notes:

  • security: Prevents excessive fees that could harm users

  • validation: Ensures fees stay within protocol limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws FeeTooHigh if fee exceeds maximum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateFee(uint256 fee, uint256 maxFee) internal pure;

Parameters

NameTypeDescription
feeuint256The fee amount to validate
maxFeeuint256The maximum allowed fee

PriceValidationLibrary

Git Source

Title: PriceValidationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Library for price validation and deviation checks

Main characteristics:

  • Price deviation checks to prevent flash loan attacks
  • Block-based validation for price freshness
  • Reduces code duplication across contracts

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.1"

Functions

checkPriceDeviation

Checks if price deviation exceeds maximum allowed

Only checks deviation if enough blocks have passed since last update

Notes:

  • security: Prevents flash loan attacks by validating price deviations

  • validation: Validates price changes are within acceptable bounds

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - returns boolean flag

  • reentrancy: Not applicable - view function

  • access: Internal library function - no access restrictions

  • oracle: Uses provided price parameters (no direct oracle calls)

function checkPriceDeviation(
    uint256 currentPrice,
    uint256 lastValidPrice,
    uint256 maxDeviation,
    uint256 lastUpdateBlock,
    uint256 minBlocksBetweenUpdates
) internal view returns (bool shouldRevert, uint256 deviationBps);

Parameters

NameTypeDescription
currentPriceuint256Current price from oracle
lastValidPriceuint256Last valid cached price
maxDeviationuint256Maximum allowed deviation in basis points
lastUpdateBlockuint256Block number of last price update
minBlocksBetweenUpdatesuint256Minimum blocks required between updates

Returns

NameTypeDescription
shouldRevertboolTrue if deviation check should cause revert
deviationBpsuint256Calculated deviation in basis points

QTITokenGovernanceLibrary

Git Source

Title: QTITokenGovernanceLibrary

Author: Quantillon Labs

Library for QTIToken governance calculations and validations

Extracts calculation logic from QTIToken to reduce contract size

Constants

MAX_LOCK_TIME

Maximum lock time for QTI tokens (1 year)

uint256 public constant MAX_LOCK_TIME = 365 days

MIN_LOCK_TIME

Minimum lock time for vote-escrow (1 week)

uint256 public constant MIN_LOCK_TIME = 7 days

MAX_VE_QTI_MULTIPLIER

Maximum voting power multiplier (4x)

uint256 public constant MAX_VE_QTI_MULTIPLIER = 4

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

calculateVotingPowerMultiplier

Calculate voting power multiplier based on lock time

Calculates linear multiplier from 1x to 4x based on lock duration

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateVotingPowerMultiplier(uint256 lockTime) external pure returns (uint256 multiplier);

Parameters

NameTypeDescription
lockTimeuint256Duration of the lock

Returns

NameTypeDescription
multiplieruint256Voting power multiplier

_calculateVotingPowerMultiplier

Internal function to calculate voting power multiplier

Calculates linear multiplier from 1x to 4x based on lock duration

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateVotingPowerMultiplier(uint256 lockTime) internal pure returns (uint256 multiplier);

Parameters

NameTypeDescription
lockTimeuint256Duration of the lock

Returns

NameTypeDescription
multiplieruint256Voting power multiplier

calculateVotingPower

Calculate voting power with overflow protection

Calculates voting power based on amount and lock time with overflow protection

Notes:

  • security: Prevents overflow in voting power calculations

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidAmount if result exceeds uint96 max

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateVotingPower(uint256 amount, uint256 lockTime) external pure returns (uint256);

Parameters

NameTypeDescription
amountuint256Amount of QTI tokens to lock
lockTimeuint256Duration to lock tokens

Returns

NameTypeDescription
<none>uint256votingPower Calculated voting power

_calculateVotingPower

Internal function to calculate voting power with overflow protection

Calculates voting power based on amount and lock time with overflow protection

Notes:

  • security: Prevents overflow in voting power calculations

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidAmount if result exceeds uint96 max

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateVotingPower(uint256 amount, uint256 lockTime) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256Amount of QTI tokens to lock
lockTimeuint256Duration to lock tokens

Returns

NameTypeDescription
<none>uint256votingPower Calculated voting power

calculateCurrentVotingPower

Calculate current voting power with linear decay

Calculates current voting power with linear decay over time

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateCurrentVotingPower(LockInfo memory lockInfo, uint256 currentTime)
    external
    pure
    returns (uint256 votingPower);

Parameters

NameTypeDescription
lockInfoLockInfoLock information structure
currentTimeuint256Current timestamp

Returns

NameTypeDescription
votingPoweruint256Current voting power of the user (decays linearly over time)

calculateUnlockTime

Calculate unlock time with proper validation

Calculates new unlock time based on current timestamp and lock duration

Notes:

  • security: Prevents timestamp overflow in unlock time calculations

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidTime if result exceeds uint32 max

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateUnlockTime(uint256 currentTimestamp, uint256 lockTime, uint256 existingUnlockTime)
    external
    pure
    returns (uint256 newUnlockTime);

Parameters

NameTypeDescription
currentTimestampuint256Current timestamp for calculation
lockTimeuint256Duration to lock tokens
existingUnlockTimeuint256Existing unlock time if already locked

Returns

NameTypeDescription
newUnlockTimeuint256Calculated unlock time

_calculateUnlockTime

Internal function to calculate unlock time with proper validation

Calculates new unlock time based on current timestamp and lock duration

Notes:

  • security: Prevents timestamp overflow in unlock time calculations

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidTime if result exceeds uint32 max

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateUnlockTime(uint256 currentTimestamp, uint256 lockTime, uint256 existingUnlockTime)
    internal
    pure
    returns (uint256 newUnlockTime);

Parameters

NameTypeDescription
currentTimestampuint256Current timestamp for calculation
lockTimeuint256Duration to lock tokens
existingUnlockTimeuint256Existing unlock time if already locked

Returns

NameTypeDescription
newUnlockTimeuint256Calculated unlock time

validateAndCalculateTotalAmount

Validate all amounts and lock times, returns total amount

Ensures all amounts and lock times are valid and calculates total amount

Notes:

  • security: Prevents invalid amounts and lock times from being processed

  • validation: Validates amounts are positive and lock times are within bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws various validation errors for invalid inputs

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function validateAndCalculateTotalAmount(uint256[] calldata amounts, uint256[] calldata lockTimes)
    external
    pure
    returns (uint256 totalAmount);

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations

Returns

NameTypeDescription
totalAmountuint256Total amount of QTI to be locked

updateLockInfo

Update lock info with overflow checks

Updates user's lock information with new amounts and times

Notes:

  • security: Prevents overflow in lock info updates

  • validation: Validates amounts and times are within bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidAmount if values exceed uint96 max

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function updateLockInfo(
    uint256 totalNewAmount,
    uint256 newUnlockTime,
    uint256 totalNewVotingPower,
    uint256 lockTime
) external pure returns (LockInfo memory updatedLockInfo);

Parameters

NameTypeDescription
totalNewAmountuint256Total new amount to lock
newUnlockTimeuint256New unlock time
totalNewVotingPoweruint256Total new voting power
lockTimeuint256Lock duration

Returns

NameTypeDescription
updatedLockInfoLockInfoUpdated lock information

calculateDecentralizationLevel

Calculate decentralization level based on time elapsed

Calculates decentralization level based on elapsed time since start

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateDecentralizationLevel(
    uint256 currentTime,
    uint256 decentralizationStartTime,
    uint256 decentralizationDuration,
    uint256 maxTimeElapsed
) external pure returns (uint256 newLevel);

Parameters

NameTypeDescription
currentTimeuint256Current timestamp
decentralizationStartTimeuint256Start time for decentralization
decentralizationDurationuint256Total duration for decentralization
maxTimeElapseduint256Maximum time elapsed to consider

Returns

NameTypeDescription
newLeveluint256New decentralization level (0-10000)

Structs

LockInfo

Lock information structure

struct LockInfo {
    uint96 amount; // Amount of QTI locked
    uint32 unlockTime; // Timestamp when lock expires
    uint96 votingPower; // Current voting power
    uint32 lastClaimTime; // Last claim time (for future use)
    uint96 initialVotingPower; // Initial voting power when locked
    uint32 lockTime; // Original lock duration
}

IReferenceConsumer

Git Source

Resolve the reference from the consumer's governed oracle binding.

Functions

oracle

Read the consumer's governed oracle address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function oracle() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

IReferenceRouter

Git Source

Router reference bindings, independent of execution quotes.

Functions

activeOracle

Read the router's active oracle slot.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function activeOracle() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8Value defined by this accessor or calculation.

marketOracle

Read the router's market-oracle address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function marketOracle() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

IReferenceAdapter

Git Source

The existing Hyperliquid adapter owns the source binding.

Functions

slippageStorage

Read the market adapter's governed snapshot-source address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function slippageStorage() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

ReferenceSettlementLibrary

Git Source

Title: ReferenceSettlementLibrary

Carry a signed valuation report with a hedger operation without changing its caller.

Linked delegatecall preserves Safe, hedger ownership, role and existing reentrancy checks.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

executeWithReference

Deliver a signed reference and execute one permitted hedger operation atomically.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function executeWithReference(bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

removeMarginWithReference

Deliver a reference and withdraw margin with explicit permissionable parameters.

Keeps calldata construction in the linked library to respect the consumer's EIP-170 limit.

Notes:

  • security: Retains the consumer's owner, pause and collateral checks.

  • validation: Report and withdrawal are validated atomically.

  • state-changes: Reference and margin accounting, or none on revert.

  • events: Underlying reference and margin events.

  • errors: Propagates reference and margin errors.

  • reentrancy: Underlying withdrawal guard remains active.

  • access: Original hedger permissions.

  • oracle: Uses the governed reference source.

function removeMarginWithReference(uint256 positionId, uint256 amount, bytes calldata authorization)
    external
    returns (bytes memory);

Parameters

NameTypeDescription
positionIduint256Position owned by the original caller.
amountuint256USDC margin to withdraw.
authorizationbytesSigned valuation report.

Returns

NameTypeDescription
<none>bytesABI-encoded result of the underlying withdrawal (empty on success).

_execute

function _execute(bytes memory callData, bytes calldata authorization) private returns (bytes memory result);

SecureUpgradeLibrary

Git Source

Title: SecureUpgradeLibrary

Linked compatibility helpers for the protocol's custom timelock interface.

The production OZ controller is scheduled directly using operation ids.

Functions

version

Semantic version of this linked library.

Preserves custom-controller compatibility through delegatecall.

Notes:

  • security: Caller enforces proposal authorization.

  • validation: The configured controller validates proposals.

  • state-changes: Only propose modifies controller state.

  • events: Controller proposal events when applicable.

  • errors: Propagates controller errors.

  • reentrancy: Calls only the configured controller.

  • access: Linked helper.

  • oracle: None.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version.

propose

Forwards a proposal to a custom timelock.

Preserves custom-controller compatibility through delegatecall.

Notes:

  • security: Caller enforces proposal authorization.

  • validation: The configured controller validates proposals.

  • state-changes: Only propose modifies controller state.

  • events: Controller proposal events when applicable.

  • errors: Propagates controller errors.

  • reentrancy: Calls only the configured controller.

  • access: Linked helper.

  • oracle: None.

function propose(
    ITimelockUpgradeable controller,
    address implementation,
    string calldata description,
    uint256 delay
) external;

Parameters

NameTypeDescription
controllerITimelockUpgradeableConfigured custom timelock.
implementationaddressProposed implementation.
descriptionstringProposal description.
delayuint256Requested delay.

pending

Returns custom timelock proposal details.

Preserves custom-controller compatibility through delegatecall.

Notes:

  • security: Caller enforces proposal authorization.

  • validation: The configured controller validates proposals.

  • state-changes: Only propose modifies controller state.

  • events: Controller proposal events when applicable.

  • errors: Propagates controller errors.

  • reentrancy: Calls only the configured controller.

  • access: Linked helper.

  • oracle: None.

function pending(ITimelockUpgradeable controller, address implementation)
    external
    view
    returns (ITimelockUpgradeable.PendingUpgrade memory proposal);

Parameters

NameTypeDescription
controllerITimelockUpgradeableConfigured custom timelock.
implementationaddressProposed implementation.

Returns

NameTypeDescription
proposalITimelockUpgradeable.PendingUpgradeProposal details or an empty record.

isPending

Reports whether a custom proposal exists.

Preserves custom-controller compatibility through delegatecall.

Notes:

  • security: Caller enforces proposal authorization.

  • validation: The configured controller validates proposals.

  • state-changes: Only propose modifies controller state.

  • events: Controller proposal events when applicable.

  • errors: Propagates controller errors.

  • reentrancy: Calls only the configured controller.

  • access: Linked helper.

  • oracle: None.

function isPending(ITimelockUpgradeable controller, address implementation) external view returns (bool);

Parameters

NameTypeDescription
controllerITimelockUpgradeableConfigured custom timelock.
implementationaddressProposed implementation.

Returns

NameTypeDescription
<none>boolWhether a proposal exists.

canExecute

Reports whether a custom proposal is executable.

Preserves custom-controller compatibility through delegatecall.

Notes:

  • security: Caller enforces proposal authorization.

  • validation: The configured controller validates proposals.

  • state-changes: Only propose modifies controller state.

  • events: Controller proposal events when applicable.

  • errors: Propagates controller errors.

  • reentrancy: Calls only the configured controller.

  • access: Linked helper.

  • oracle: None.

function canExecute(ITimelockUpgradeable controller, address implementation) external view returns (bool);

Parameters

NameTypeDescription
controllerITimelockUpgradeableConfigured custom timelock.
implementationaddressProposed implementation.

Returns

NameTypeDescription
<none>boolWhether the controller permits execution.

SignedQuoteErrors

Git Source

Errors shared by signed execution and reference validation.

Errors

InvalidBinding

error InvalidBinding();

InvalidSignature

error InvalidSignature();

InvalidTime

error InvalidTime();

InvalidReport

error InvalidReport();

QuoteRequired

error QuoteRequired();

QuoteConsumed

error QuoteConsumed();

InvalidMode

error InvalidMode();

CapacityExceeded

error CapacityExceeded();

InvalidAmount

error InvalidAmount();

ExcessiveImpact

error ExcessiveImpact();

ActiveSettlement

error ActiveSettlement();

SignedQuoteTypes

Git Source

Title: SignedQuoteTypes

Wire types shared by the vault, signers and report consumers.

Constants

VERSION

string internal constant VERSION = "1.0.0"

Structs

Quote

Exact public settlement, or bounded yield conversion. Calldata binds the complete route.

Yield amountIn is a maximum and amountOut is the output at that maximum.

struct Quote {
    address user;
    address caller;
    Action action;
    uint256 amountIn;
    uint256 amountOut;
    uint256 observedAt;
    uint256 validAfter;
    uint256 validUntil;
    uint256 nonce;
    uint256 epoch;
    bytes32 callHash;
    bytes32 referenceHash;
}

ReferenceReport

Original market observation, never timestamped at submission.

struct ReferenceReport {
    uint256 price;
    uint256 observedAt;
    uint256 sequence;
    uint256 epoch;
}

CapacityReport

Lifetime fill acknowledgments and additional venue margin capacity.

canonicalBlock/hash identify the Base state actually reconciled by the reporter.

struct CapacityReport {
    uint256 acknowledgedBuy;
    uint256 acknowledgedSell;
    uint256 capacity;
    uint256 observedAt;
    uint256 sequence;
    uint256 epoch;
    uint256 canonicalBlock;
    bytes32 canonicalBlockHash;
}

Authorization

Reports carried atomically with a settlement.

struct Authorization {
    Quote quote;
    bytes signature;
    ReferenceReport referenceReport;
    bytes referenceSignature;
    CapacityReport capacityReport;
    bytes capacitySignature;
}

Enums

Action

enum Action {
    Mint,
    Redeem,
    Yield
}

Mode

enum Mode {
    Paused,
    Signed,
    EmergencyRedeem
}

IQuoteVaultView

Git Source

Functions

signedExecutionEnabled

Read whether the vault requires signed settlement.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function signedExecutionEnabled() external view returns (bool);

Returns

NameTypeDescription
<none>boolValue defined by this accessor or calculation.

userPool

Read the configured UserPool address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function userPool() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

executionPricing

Read the configured execution module address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function executionPricing() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

SignedSettlementLibrary

Git Source

Title: SignedSettlementLibrary

Linked entrypoint that keeps signature decoding outside the size-constrained vault.

Delegatecall retains the original payer and the existing guarded settlement functions.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

executeWithQuote

Dispatch one signed operation with the original caller and existing accounting.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function executeWithQuote(bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

preparePoolQuote

Begin an atomic pool route bound to its original user and complete calldata.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function preparePoolQuote(address user, bytes calldata callData, bytes calldata authorization) external;

Parameters

NameTypeDescription
useraddressOriginal payer whose nonce and settlement are bound.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

finishPoolQuote

Finish the atomic pool route after its conversion has been consumed.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function finishPoolQuote() external;

emergencyRedeemQEURO

Run the governed budgeted emergency redemption path.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function emergencyRedeemQEURO(uint256 amount, uint256 minimum) external;

Parameters

NameTypeDescription
amountuint256Amount in the token units of the selected operation.
minimumuint256Minimum acceptable output in the output token's raw units.

execute

Dispatch the permitted operation while preserving the consumer's original caller.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function execute(address module, bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
moduleaddressExecution module already bound by the calling vault.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

_execute

function _execute(address module, bytes calldata callData, bytes calldata authorization)
    private
    returns (bytes memory result);

_preparePool

function _preparePool(address module, address user, bytes calldata callData, bytes calldata authorization) private;

emergencyRedeem

Run the vault redemption with a bounded emergency context.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function emergencyRedeem(address module, uint256 amount, uint256 minimum) external;

Parameters

NameTypeDescription
moduleaddressExecution module already bound by the calling vault.
amountuint256Amount in the token units of the selected operation.
minimumuint256Minimum acceptable output in the output token's raw units.

_emergencyRedeem

function _emergencyRedeem(address module, uint256 amount, uint256 minimum) private;

_finishPool

function _finishPool(address module) private;

stake

Deposit newly minted QEURO and enforce the actual minimum share output.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function stake(address token, address shares, uint256 amount, uint256 minimum) external returns (uint256 minted);

Parameters

NameTypeDescription
tokenaddressToken whose balances and transfers are checked.
sharesaddressstQEURO share token receiving the deposit.
amountuint256Amount in the token units of the selected operation.
minimumuint256Minimum acceptable output in the output token's raw units.

Returns

NameTypeDescription
minteduint256Value defined by this accessor or calculation.

_dispatch

function _dispatch(bytes memory callData) private returns (bytes memory result);

IQuotePoolVault

Git Source

Functions

preparePoolQuote

Begin an atomic pool route bound to its original user and complete calldata.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: None.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function preparePoolQuote(address user, bytes calldata callData, bytes calldata authorization) external;

Parameters

NameTypeDescription
useraddressOriginal payer whose nonce and settlement are bound.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

finishPoolQuote

Finish the atomic pool route after its conversion has been consumed.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: None.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function finishPoolQuote() external;

SignedUserPoolLibrary

Git Source

Linked UserPool wrapper, preserving sender, existing guards and storage layout.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

execute

Dispatch the permitted operation while preserving the consumer's original caller.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function execute(address vault, bytes calldata callData, bytes calldata authorization)
    external
    returns (bytes memory result);

Parameters

NameTypeDescription
vaultaddressConfigured vault that owns execution authorization.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authorizationbytesABI-encoded report or quote authorization required by this entrypoint.

Returns

NameTypeDescription
resultbytesABI-encoded return data of the dispatched operation.

IYieldDistributionVault

Git Source

Inherits: IQuantillonVault

Vault getters used by linked distribution code to keep proxy runtime compact.

Functions

hedgerPool

Configured hedger accounting contract.

Read from the calling vault during library delegatecall.

Notes:

  • security: Read-only vault getter.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: View only.

  • access: Public.

  • oracle: None.

function hedgerPool() external view returns (address);

Returns

NameTypeDescription
<none>addressConfigured address.

treasury

Protocol treasury recipient.

Read from the calling vault during library delegatecall.

Notes:

  • security: Read-only vault getter.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: View only.

  • access: Public.

  • oracle: None.

function treasury() external view returns (address);

Returns

NameTypeDescription
<none>addressConfigured address.

yieldDistributionConfig

Capital distribution haircut, recipient and last harvest.

Read from the calling vault during library delegatecall.

Notes:

  • security: Read-only vault getter.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: View only.

  • access: Public.

  • oracle: None.

function yieldDistributionConfig(uint256 vaultId) external view returns (uint256, address, uint256);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
<none>uint256Haircut basis points.
<none>addressHedger recipient.
<none>uint256Last successful harvest timestamp.

StakingYieldLibrary

Git Source

Title: StakingYieldLibrary

External (linked) library holding the stQEURO yield-distribution split, extracted from QuantillonVault to keep that contract under the EIP-170 24,576-byte runtime limit.

Called via delegatecall from QuantillonVault, so external calls (adapter harvest, USDC transfers) execute in the vault's context (address(this) == vault). The vault performs the stQEURO credit and event emission; this library realizes the yield, computes the hedger / staker / treasury split, and routes the hedger and treasury shares.

Constants

BPS_DENOMINATOR

uint256 private constant BPS_DENOMINATOR = 10000

Functions

setPriority

Replaces the withdrawal priority with unique configured adapter ids.

Prevents duplicate principal accounting in priority-dependent views.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Rejects inactive, duplicate, zero, or unconfigured ids.

  • state-changes: Replaces priority storage.

  • events: RedemptionPriorityUpdated.

  • errors: InvalidVault or ZeroAddress.

  • reentrancy: No external calls.

  • access: Linked library.

  • oracle: None.

function setPriority(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    uint256[] storage priority,
    uint256[] calldata ids
) external;

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active flags.
priorityuint256[]Existing priority storage.
idsuint256[]Requested ids.

validateRedemptionCoverage

Requires the effective redemption set to cover all tracked external principal.

The priority setter guarantees unique ids; an empty list selects only the default.

Notes:

  • security: Prevents configuration from omitting funded collateral.

  • validation: Sum of included principal must equal the aggregate tracker.

  • state-changes: None.

  • events: None.

  • errors: InvalidCondition or arithmetic overflow.

  • reentrancy: No external calls.

  • access: Linked library; caller enforces governance authorization.

  • oracle: None.

function validateRedemptionCoverage(
    mapping(uint256 => uint256) storage principal,
    uint256[] storage priority,
    uint256 defaultId,
    uint256 totalPrincipal
) external view;

Parameters

NameTypeDescription
principalmapping(uint256 => uint256)Tracked principal by vault id.
priorityuint256[]Unique ordered redemption ids.
defaultIduint256Fallback id when priority is empty.
totalPrincipaluint256Aggregate tracked external principal.

configureAdapter

Configures an external adapter while preserving tracked collateral.

Funded replacements require a paused vault, empty old adapter, and funded new adapter.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Rejects disabling funded adapters and unfunded replacements.

  • state-changes: Updates registry and active flag.

  • events: StakingVaultConfigured.

  • errors: InvalidVault, ZeroAddress, InvalidCondition.

  • reentrancy: External adapter calls are view-only.

  • access: Linked library.

  • oracle: None.

function configureAdapter(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    mapping(uint256 => uint256) storage principal,
    uint256 id,
    address next,
    bool enabled,
    bool isPaused
) external;

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active adapter flags.
principalmapping(uint256 => uint256)Tracked principal by vault.
iduint256Vault id.
nextaddressNew adapter.
enabledboolRequested active flag.
isPausedboolVault pause state.

realizeLoss

Records reduced external collateral without changing hedger margin.

The caller deducts the returned loss from aggregate external principal.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Adapter must exist and report less underlying than tracked principal.

  • state-changes: Reduces per-vault principal.

  • events: ExternalVaultLossRealized.

  • errors: InvalidVault or InvalidCondition.

  • reentrancy: View-only adapter call.

  • access: Linked library.

  • oracle: None.

function realizeLoss(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => uint256) storage principal,
    uint256 id
) external returns (uint256 loss);

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
principalmapping(uint256 => uint256)Tracked principal by vault.
iduint256Vault id.

Returns

NameTypeDescription
lossuint256USDC principal loss recognized.

registerToken

Registers and verifies a deterministic per-vault staking token.

Preserves registry binding before the external factory call.

Notes:

  • security: Vault wrapper enforces governance and nonReentrant.

  • validation: Requires a fresh valid binding and matching preview.

  • state-changes: Stores token binding.

  • events: Factory emits registration events; caller emits local registration.

  • errors: InvalidToken, InvalidVault, AlreadyInitialized, InvalidAddress.

  • reentrancy: Caller holds the guard.

  • access: Linked library.

  • oracle: None.

function registerToken(
    mapping(uint256 => address) storage tokens,
    address factory,
    uint256 id,
    string calldata name
) external returns (address token);

Parameters

NameTypeDescription
tokensmapping(uint256 => address)Per-vault staking token registry.
factoryaddressFactory address.
iduint256Vault identifier.
namestringVault name.

Returns

NameTypeDescription
tokenaddressRegistered staking token.

withdrawPrincipal

Sources an exact aggregate payout from priority-ordered adapters.

Requires every adapter to return the exact requested amount and verifies the balance delta. Adapters must absorb any rounding dust internally before returning.

Notes:

  • security: Delegatecalled from guarded vault settlement.

  • validation: Requires exact aggregate liquidity and verifies adapter balance deltas.

  • state-changes: Reduces per-adapter principal; caller reduces aggregate principal.

  • events: UsdcWithdrawnFromExternalVault.

  • errors: InvalidAmount or InsufficientBalance.

  • reentrancy: Caller holds nonReentrant guard.

  • access: Linked library.

  • oracle: None.

function withdrawPrincipal(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    mapping(uint256 => uint256) storage principal,
    uint256[] memory priority,
    uint256 amount,
    IERC20 usdc
) external returns (uint256 withdrawn);

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active adapter flags.
principalmapping(uint256 => uint256)Per-adapter tracked principal.
priorityuint256[]Ordered source identifiers.
amountuint256Exact USDC deficit to source.
usdcIERC20Collateral token.

Returns

NameTypeDescription
withdrawnuint256Aggregate transferred USDC.

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

calculateSplit

Calculate conserved staking-ratio allocations of realized yield.

Floors gross staker yield and the haircut; staking-ratio dust goes to treasury and haircut dust to stakers.

Notes:

  • security: Never deducts principal; allocations sum to yieldUsdc.

  • validation: Haircut cannot exceed 100%.

  • state-changes: None.

  • events: None.

  • errors: AboveLimit for an invalid haircut.

  • reentrancy: No external calls.

  • access: Public library calculation.

  • oracle: No price used in allocation.

function calculateSplit(uint256 yieldUsdc, Capital memory c, uint256 haircutBps)
    public
    pure
    returns (Split memory s);

Parameters

NameTypeDescription
yieldUsdcuint256Realized USDC yield.
cCapitalStaking ownership snapshot; retired capital fields are ignored.
haircutBpsuint256Percentage of gross staker yield, in basis points.

Returns

NameTypeDescription
sSplitDistribution before execution costs.

_params

Resolve the calling vault's configuration before taking a staking snapshot.

Only called by delegatecall entrypoints; external self-calls read public vault getters.

function _params(uint256 vaultId) private view returns (DistributeParams memory p);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
pDistributeParamsValidated configuration.

_snapshot

Snapshot staking ownership and enforce the single-funded-strategy distribution boundary.

Registered token balances include credited unvested QEURO when shareholders exist.

Notes:

  • security: Fails closed on unsupported strategies or invalid accounting reads.

  • validation: All external principal and all outstanding staking shares must belong to this series.

  • state-changes: None.

  • events: None.

  • errors: InvalidCondition, InvalidVault, or propagated external errors.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Internal library helper.

  • oracle: None; conversion validates prices separately.

function _snapshot(DistributeParams memory p) private view returns (Capital memory c);

Parameters

NameTypeDescription
pDistributeParamsCalling vault configuration.

Returns

NameTypeDescription
cCapitalEconomic ownership before harvest and minting.

previewSplit

Preview the next distribution with the same ownership calculation as execution.

Call through eth_call. Actual realized yield may differ due to available withdrawal liquidity.

Notes:

  • security: Shares execution validation and requires a recipient for nonzero hedger payments.

  • validation: Validates the strategy boundary and any nonzero hedger recipient.

  • state-changes: None.

  • events: None.

  • errors: Propagates snapshot errors; ZeroAddress for a missing hedger recipient.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Linked library.

  • oracle: None; conversion validates prices separately.

function previewSplit(uint256 vaultId) external returns (Split memory s);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
sSplitEstimated USDC allocations before execution costs.

harvestAndSplit

Harvest and allocate yield by the staking ratio, with a haircut on gross staking yield.

The vault credits userShare via its existing QEURO mint path. Failure rolls back the whole harvest.

Notes:

  • security: Principal is untouched; no fallback recipient silently captures hedger yield.

  • validation: Same staking validation as preview; nonzero hedger payout requires a recipient.

  • state-changes: Harvests adapter yield and transfers hedger/treasury USDC.

  • events: Adapter/token events; the vault emits distribution events.

  • errors: Propagates snapshot/adapter/token errors; ZeroAddress for missing recipient.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Linked library.

  • oracle: No price used for allocation; ownership is sampled before harvesting and minting.

function harvestAndSplit(uint256 vaultId, mapping(uint256 => uint256) storage lastHarvest)
    external
    returns (uint256 userShare);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.
lastHarvestmapping(uint256 => uint256)Keeper timestamps updated atomically with distribution.

Returns

NameTypeDescription
userShareuint256USDC allocation to credit through the existing QEURO mint path.

Events

UsdcWithdrawnFromExternalVault

event UsdcWithdrawnFromExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalAfter);

StakingVaultConfigured

event StakingVaultConfigured(uint256 indexed vaultId, address indexed adapter, bool active);

ExternalVaultLossRealized

event ExternalVaultLossRealized(uint256 indexed vaultId, uint256 previousPrincipal, uint256 currentUnderlying);

RedemptionPriorityUpdated

event RedemptionPriorityUpdated(uint256[] vaultIds);

VaultYieldDistributed

event VaultYieldDistributed(
    uint256 indexed vaultId, uint256 realizedYield, uint256 hedgerShare, uint256 userShare, uint256 treasuryShare
);

VaultYieldBreakdown

event VaultYieldBreakdown(uint256 indexed vaultId, uint256 hedgerBase, uint256 stakingYieldHaircut);

Structs

DistributeParams

Configuration and strategy registries supplied by the calling vault.

struct DistributeParams {
    address adapter;
    address stToken;
    address qeuro;
    address usdc;
    address treasury;
    address hedgerRecipient;
    uint256 principalUsdc;
    uint256 totalPrincipalUsdc;
    uint256 haircutBps;
    address factory;
    address hedgerPool;
    address oracle;
    uint256 vaultId;
}

Split

USDC allocations before execution costs; hedgerBase is retired and always zero.

struct Split {
    uint256 realizedYield;
    uint256 hedgerBase;
    uint256 haircut;
    uint256 hedgerShare;
    uint256 userShare;
    uint256 treasuryShare;
}

Capital

Harvest-time staking snapshot; hedger and userBacking are retired ABI fields.

struct Capital {
    uint256 hedger;
    uint256 userBacking;
    uint256 staked;
    uint256 supply;
}

TimeProvider

Git Source

Inherits: Initializable, AccessControlUpgradeable, UUPSUpgradeable, IVersioned

Title: TimeProvider

Centralized time provider for the Quantillon Protocol

Provides a controlled time source that can be adjusted for testing and emergency scenarios SECURITY CONSIDERATIONS:

  • Only governance can adjust time offset
  • Time offset is limited to prevent abuse
  • Emergency reset capability for security incidents
  • All time adjustments are logged for transparency

Constants

GOVERNANCE_ROLE

Role identifier for governance operations

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

Role identifier for emergency operations

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role identifier for upgrade operations

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_TIME_OFFSET

Maximum allowed time offset (7 days) to prevent abuse

uint256 public constant MAX_TIME_OFFSET = 7 days

MAX_TIME_DRIFT

Maximum allowed time drift (1 hour) for normal operations

uint256 public constant MAX_TIME_DRIFT = 1 hours

State Variables

timeOffset

Current time offset applied to block.timestamp

Can be positive (time advancement) or negative (time delay) within limits

int256 public timeOffset

lastOffsetChange

Timestamp when the time offset was last modified

uint256 public lastOffsetChange

emergencyMode

Flag indicating if time provider is in emergency mode

bool public emergencyMode

adjustmentCounter

Counter for time adjustments (for tracking)

uint256 public adjustmentCounter

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

whenNotEmergency

Ensures the contract is not in emergency mode

modifier whenNotEmergency() ;

_whenNotEmergency

Reverts if contract is in emergency mode

Used by whenNotEmergency modifier; blocks operations when emergencyMode is true

Notes:

  • security: Prevents operations during emergency

  • validation: emergencyMode must be false

  • state-changes: None

  • events: None

  • errors: EmergencyModeActive if emergencyMode

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _whenNotEmergency() internal view;

validTimeOffset

Ensures the time offset is within allowed bounds

modifier validTimeOffset(int256 offset) ;

_validTimeOffset

Reverts if time offset exceeds MAX_TIME_OFFSET (absolute value)

Used by validTimeOffset modifier; bounds allowed time manipulation

Notes:

  • security: Bounds check only

  • validation: |offset| <= MAX_TIME_OFFSET

  • state-changes: None

  • events: None

  • errors: InvalidAmount if offset out of bounds

  • reentrancy: No external calls

  • access: Internal; used by modifier

  • oracle: None

function _validTimeOffset(int256 offset) internal pure;

Parameters

NameTypeDescription
offsetint256Signed time offset in seconds

constructor

Constructor for TimeProvider contract

Disables initializers for proxy pattern compatibility

Notes:

  • security: No security validations required - constructor

  • validation: No input validation required - constructor

  • state-changes: Disables initializers for proxy pattern

  • events: No events emitted

  • errors: No errors thrown - safe constructor

  • reentrancy: Not applicable - constructor

  • access: Public - anyone can deploy

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the TimeProvider contract

Sets up access control roles and initializes state variables

Notes:

  • security: Validates all addresses are not zero, grants admin roles

  • validation: Validates all input addresses are not address(0)

  • state-changes: Initializes all state variables, sets default values

  • events: No events emitted during initialization

  • errors: Throws ZeroAddress if any address is address(0)

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during deployment

  • oracle: No oracle dependencies

function initialize(address admin, address governance, address emergency) external initializer;

Parameters

NameTypeDescription
adminaddressThe address that will be granted DEFAULT_ADMIN_ROLE
governanceaddressThe address that will be granted GOVERNANCE_ROLE
emergencyaddressThe address that will be granted EMERGENCY_ROLE

currentTime

Returns the current time according to this provider

Returns block.timestamp adjusted by the current time offset

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query current time

  • oracle: No oracle dependencies

function currentTime() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current timestamp adjusted by the offset

_getCurrentTime

Returns the current time according to this provider (internal)

Internal function that applies time offset to block.timestamp with underflow protection

Notes:

  • security: Validates time offset calculations to prevent underflow

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _getCurrentTime() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current timestamp adjusted by the offset

rawTimestamp

Returns the raw block timestamp without any offset

Returns unmodified block.timestamp for comparison purposes

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query raw timestamp

  • oracle: No oracle dependencies

function rawTimestamp() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Raw block.timestamp

setTimeOffset

Sets the time offset (governance only)

Allows governance to set a new time offset within allowed bounds

Notes:

  • security: Validates governance role and time offset bounds

  • validation: Validates newOffset is within MAX_TIME_OFFSET limits

  • state-changes: Updates timeOffset, lastOffsetChange, adjustmentCounter

  • events: Emits TimeOffsetChanged with old and new offset values

  • errors: Throws InvalidAmount if offset exceeds MAX_TIME_OFFSET

  • reentrancy: Not protected - no external calls

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function setTimeOffset(int256 newOffset, string calldata reason)
    external
    onlyRole(GOVERNANCE_ROLE)
    whenNotEmergency
    validTimeOffset(newOffset);

Parameters

NameTypeDescription
newOffsetint256The new time offset to apply
reasonstringHuman-readable reason for the change

advanceTime

Advances time by a specific amount (governance only)

Adds advancement to current time offset, handling both positive and negative offsets

Notes:

  • security: Validates governance role and advancement amount

  • validation: Validates advancement > 0 and resulting offset within bounds

  • state-changes: Updates timeOffset, lastOffsetChange, adjustmentCounter

  • events: Emits TimeOffsetChanged with old and new offset values

  • errors: Throws InvalidAmount if advancement is 0 or exceeds bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function advanceTime(uint256 advancement, string calldata reason)
    external
    onlyRole(GOVERNANCE_ROLE)
    whenNotEmergency;

Parameters

NameTypeDescription
advancementuint256Amount of time to advance (in seconds)
reasonstringHuman-readable reason for the advancement

resetTime

Resets time to normal (no offset)

Sets time offset to 0, returning to normal block.timestamp behavior

Notes:

  • security: Validates governance role authorization

  • validation: No input validation required

  • state-changes: Updates timeOffset to 0, lastOffsetChange, adjustmentCounter

  • events: Emits TimeReset and TimeOffsetChanged events

  • errors: No errors thrown - safe reset operation

  • reentrancy: Not protected - no external calls

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function resetTime() external onlyRole(GOVERNANCE_ROLE);

setEmergencyMode

Toggles emergency mode (emergency role only)

Enables or disables emergency mode, automatically resetting time offset when enabled

Notes:

  • security: Validates emergency role authorization

  • validation: No input validation required

  • state-changes: Updates emergencyMode flag, resets timeOffset if enabling

  • events: Emits EmergencyModeChanged and TimeOffsetChanged if reset

  • errors: No errors thrown - safe mode toggle

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function setEmergencyMode(bool enabled) external onlyRole(EMERGENCY_ROLE);

Parameters

NameTypeDescription
enabledboolWhether to enable or disable emergency mode

emergencyResetTime

Emergency time reset (emergency role only)

Emergency function to immediately reset time offset to 0

Notes:

  • security: Validates emergency role authorization

  • validation: No input validation required

  • state-changes: Updates timeOffset to 0, lastOffsetChange, adjustmentCounter

  • events: Emits TimeReset and TimeOffsetChanged events

  • errors: No errors thrown - safe emergency reset

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function emergencyResetTime() external onlyRole(EMERGENCY_ROLE);

getTimeInfo

Returns detailed time information

Provides comprehensive time data including provider time, raw timestamp, offset, and emergency status

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query time information

  • oracle: No oracle dependencies

function getTimeInfo()
    external
    view
    returns (uint256 currentProviderTime, uint256 rawBlockTimestamp, int256 currentOffset, bool isEmergency);

Returns

NameTypeDescription
currentProviderTimeuint256Current time according to provider
rawBlockTimestampuint256Raw block timestamp
currentOffsetint256Current time offset
isEmergencyboolWhether emergency mode is active

timeDiff

Calculates time difference between two timestamps according to provider

Pure function that calculates signed time difference between two timestamps

Notes:

  • security: No security validations required - pure function

  • validation: No input validation required - pure function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - pure function

  • access: Public - anyone can calculate time difference

  • oracle: No oracle dependencies

function timeDiff(uint256 timestamp1, uint256 timestamp2) external pure returns (int256);

Parameters

NameTypeDescription
timestamp1uint256First timestamp
timestamp2uint256Second timestamp

Returns

NameTypeDescription
<none>int256Time difference (timestamp1 - timestamp2)

_authorizeUpgrade

Authorizes contract upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function _authorizeUpgrade(address newImplementation) internal view override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

Events

TimeOffsetChanged

Emitted when time offset is changed

event TimeOffsetChanged(
    address indexed changer, int256 oldOffset, int256 newOffset, string reason, uint256 timestamp
);

EmergencyModeChanged

Emitted when emergency mode is toggled

event EmergencyModeChanged(bool enabled, address indexed changer, uint256 timestamp);

TimeReset

Emitted when time is reset to normal

event TimeReset(address indexed resetter, uint256 timestamp);

TokenErrorLibrary

Git Source

Title: TokenErrorLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Token-specific errors for QEURO, QTI, and stQEURO tokens

Main characteristics:

  • Errors specific to token operations
  • Minting and burning errors
  • Blacklist and whitelist errors
  • Supply and cap management errors

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Errors

MintingDisabled

error MintingDisabled();

BlacklistedAddress

error BlacklistedAddress();

NewCapBelowCurrentSupply

error NewCapBelowCurrentSupply();

LockNotExpired

error LockNotExpired();

NothingToUnlock

error NothingToUnlock();

RateLimitExceeded

error RateLimitExceeded();

AlreadyBlacklisted

error AlreadyBlacklisted();

NotBlacklisted

error NotBlacklisted();

AlreadyWhitelisted

error AlreadyWhitelisted();

PrecisionTooHigh

error PrecisionTooHigh();

TooManyDecimals

error TooManyDecimals();

TokenLibrary

Git Source

Title: TokenLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Library for essential token operations to reduce contract bytecode size

This library provides core token validation functions:

  • Mint and burn parameter validation with supply cap checks
  • Used by QEURO token for secure minting and burning operations

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

validateMint

Validates mint parameters

Ensures minting doesn't exceed maximum supply and validates parameters

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function validateMint(address to, uint256 amount, uint256 totalSupply, uint256 maxSupply) internal pure;

Parameters

NameTypeDescription
toaddressAddress to mint to
amountuint256Amount to mint
totalSupplyuint256Current total supply
maxSupplyuint256Maximum supply cap

validateBurn

Validates burn parameters

Ensures sufficient balance and validates parameters for burning

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function validateBurn(address from, uint256 amount, uint256 balance) internal pure;

Parameters

NameTypeDescription
fromaddressAddress to burn from
amountuint256Amount to burn
balanceuint256Current balance

TreasuryRecoveryLibrary

Git Source

Title: TreasuryRecoveryLibrary

Author: Quantillon Protocol Team

Library for secure token and ETH recovery to treasury addresses

This library factorizes the recoverToken and recoverETH functionality used across all contracts to save gas, reduce bytecode, and ensure consistent security implementation

Note: security-contact: team@quantillon.money

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

recoverToken

Recover tokens accidentally sent to the contract to treasury only

SECURITY: Prevents recovery of own tokens and sends only to treasury

Gas optimization: Uses library function to avoid code duplication

Security: Prevents recovery of own tokens and ensures treasury-only recovery

Error handling: Uses custom errors for gas efficiency

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverToken(address token, uint256 amount, address contractAddress, address treasury) external;

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to recover
contractAddressaddressAddress of the calling contract (for own token check)
treasuryaddressTreasury address to send recovered tokens to

UserPoolStakingLibrary

Git Source

Title: UserPoolStakingLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Staking and reward calculation functions for UserPool to reduce contract size

Extracted from UserPool to reduce bytecode size and improve maintainability

Note: security-contact: team@quantillon.money

Constants

MIN_STAKE_AMOUNT

uint256 public constant MIN_STAKE_AMOUNT = 1e18

MAX_STAKE_AMOUNT

uint256 public constant MAX_STAKE_AMOUNT = 1000000e18

MIN_STAKE_DURATION

uint256 public constant MIN_STAKE_DURATION = 1 days

MAX_STAKE_DURATION

uint256 public constant MAX_STAKE_DURATION = 365 days

UNSTAKE_COOLDOWN

uint256 public constant UNSTAKE_COOLDOWN = 7 days

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

_calculateStakingRewards

Calculates staking rewards for a user

Internal function to calculate rewards based on stake duration and APY

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateStakingRewards(StakeInfo memory stakeInfo, uint256 stakingAPY, uint256 currentTime)
    internal
    pure
    returns (uint256 rewards);

Parameters

NameTypeDescription
stakeInfoStakeInfoStake information
stakingAPYuint256Staking APY in basis points
currentTimeuint256Current timestamp

Returns

NameTypeDescription
rewardsuint256Calculated rewards

calculateStakingRewards

Public wrapper for calculateStakingRewards

Public interface for calculating staking rewards

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateStakingRewards(StakeInfo memory stakeInfo, uint256 stakingAPY, uint256 currentTime)
    external
    pure
    returns (uint256 rewards);

Parameters

NameTypeDescription
stakeInfoStakeInfoStake information
stakingAPYuint256Staking APY in basis points
currentTimeuint256Current timestamp

Returns

NameTypeDescription
rewardsuint256Calculated rewards

Structs

StakeInfo

struct StakeInfo {
    uint256 amount;
    uint256 startTime;
    uint256 endTime;
    uint256 lastRewardClaim;
    uint256 totalRewardsClaimed;
    bool isActive;
}

UserStakingData

struct UserStakingData {
    uint256 totalStaked;
    uint256 totalRewardsEarned;
    uint256 totalRewardsClaimed;
    uint256 lastStakeTime;
    uint256 lastUnstakeTime;
    uint256 activeStakes;
}

VaultCollateralLibrary

Git Source

Linked collateral helpers preserving loss-aware principal accounting.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

collateral

Sum external principal capped by each adapter's recoverable underlying.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function collateral(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => uint256) storage principal,
    uint256[] storage priority,
    uint256 defaultId
) external view returns (uint256 total);

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Vault storage mapping from IDs to adapters.
principalmapping(uint256 => uint256)Vault storage mapping of tracked USDC principal.
priorityuint256[]Configured redemption order in vault storage.
defaultIduint256Default vault used when no explicit redemption order exists.

Returns

NameTypeDescription
totaluint256Value defined by this accessor or calculation.

validateRouting

Require an enabled adapter belonging to the configured redemption set.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function validateRouting(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage enabled,
    uint256[] storage priority,
    uint256 defaultId,
    uint256 id
) external view;

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Vault storage mapping from IDs to adapters.
enabledmapping(uint256 => bool)Enabled-vault mapping, or requested emergency state for the reference source.
priorityuint256[]Configured redemption order in vault storage.
defaultIduint256Default vault used when no explicit redemption order exists.
iduint256External vault identifier.

inSet

Check whether an external vault belongs to the redemption set.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function inSet(uint256[] storage priority, uint256 defaultId, uint256 id) external view returns (bool);

Parameters

NameTypeDescription
priorityuint256[]Configured redemption order in vault storage.
defaultIduint256Default vault used when no explicit redemption order exists.
iduint256External vault identifier.

Returns

NameTypeDescription
<none>boolValue defined by this accessor or calculation.

_inSet

function _inSet(uint256[] storage priority, uint256 defaultId, uint256 id) private view returns (bool);

_value

function _value(IExternalStakingVault adapter, uint256 principal) private view returns (uint256);

withdrawFees

Transfer only the vault token balance exceeding accounted collateral.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function withdrawFees(IERC20 token, address recipient, uint256 held) external;

Parameters

NameTypeDescription
tokenIERC20Token whose balances and transfers are checked.
recipientaddressAddress receiving the output transfer.
helduint256Accounted collateral that cannot be withdrawn as fees.

VaultErrorLibrary

Git Source

Title: VaultErrorLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Vault-specific errors for QuantillonVault and related operations

Main characteristics:

  • Errors specific to vault operations
  • Fee validation errors

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Errors

FeeTooHigh

error FeeTooHigh();

VaultMath

Git Source

Title: VaultMath

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Mathematical operations library for Quantillon Protocol

This library provides essential mathematical utilities:

  • Percentage calculations for fees and yield distributions
  • Min/max value selection for safe boundaries
  • Decimal scaling utilities for different token precisions

Note: security-contact: team@quantillon.money

Constants

BASIS_POINTS

Precision for percentage calculations (10000 = 100%)

uint256 public constant BASIS_POINTS = 10000

PRECISION

High precision scalar (18 decimals)

uint256 public constant PRECISION = 1e18

MAX_PERCENTAGE

Maximum allowed percentage (10000%)

uint256 public constant MAX_PERCENTAGE = 1000000

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

mulDiv

Multiply two numbers and divide by a third with rounding

Used by percentageOf for fee calculations

Notes:

  • security: Prevents division by zero and multiplication overflow

  • validation: Validates c != 0, checks for multiplication overflow

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws "Division by zero" if c is 0, "Multiplication overflow" if overflow

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function mulDiv(uint256 a, uint256 b, uint256 c) internal pure returns (uint256 result);

Parameters

NameTypeDescription
auint256First number
buint256Second number
cuint256Divisor

Returns

NameTypeDescription
resultuint256a * b / c with proper rounding

percentageOf

Calculate percentage of a value

Used for fee calculations across all contracts

Notes:

  • security: Prevents percentage overflow and division by zero

  • validation: Validates percentage <= MAX_PERCENTAGE

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws "Percentage too high" if percentage > MAX_PERCENTAGE

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function percentageOf(uint256 value, uint256 percentage) internal pure returns (uint256);

Parameters

NameTypeDescription
valueuint256Base value
percentageuint256Percentage in basis points (e.g., 500 = 5%)

Returns

NameTypeDescription
<none>uint256Calculated percentage value

scaleDecimals

Scale a value between different decimal precisions with proper rounding

Used for converting between token precisions (e.g., USDC 6 decimals to 18 decimals)

Notes:

  • security: Pure; no overflow for typical decimals

  • validation: fromDecimals/toDecimals are uint8

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function scaleDecimals(uint256 value, uint8 fromDecimals, uint8 toDecimals)
    internal
    pure
    returns (uint256 scaledValue);

Parameters

NameTypeDescription
valueuint256Original value
fromDecimalsuint8Original decimal places
toDecimalsuint8Target decimal places

Returns

NameTypeDescription
scaledValueuint256Scaled value with proper rounding

ITransferVault

Git Source

Functions

usdc

Read the configured collateral token address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

qeuro

Read the configured QEURO token address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function qeuro() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

executionPricing

Read the configured execution module address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function executionPricing() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

hedgerPool

Read the configured hedger accounting pool.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function hedgerPool() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

feeCollector

Read the configured protocol fee collector.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function feeCollector() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

hedgerRewardFeeSplit

Read the fee allocation to the hedger reserve, in 1e18 precision.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function hedgerRewardFeeSplit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

getVaultExposure

Read the adapter, activity and tracked principal through the vault's public view.

Private routing mappings have no generated external getters.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Adapter reads fail closed.

  • state-changes: None.

  • events: None.

  • errors: Propagates adapter read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No oracle dependency.

function getVaultExposure(uint256 vaultId)
    external
    view
    returns (address adapter, bool active, uint256 principalTracked, uint256 currentUnderlying);

Parameters

NameTypeDescription
vaultIduint256External strategy identifier.

Returns

NameTypeDescription
adapteraddressConfigured external adapter.
activeboolWhether the strategy accepts deposits.
principalTrackeduint256Recorded USDC principal, including committed mint backing.
currentUnderlyinguint256Underlying reported by the adapter.

VaultTransferLibrary

Git Source

Linked token interactions after the vault has persisted its accounting effects.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

mint

Receive USDC, route fees and spread, mint QEURO and deploy selected backing.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function mint(
    address payer,
    address recipient,
    uint256 input,
    uint256 fee,
    uint256 backing,
    uint256 output,
    uint256 route
) external;

Parameters

NameTypeDescription
payeraddressAddress from which input tokens are collected.
recipientaddressAddress receiving the output transfer.
inputuint256Gross input amount in input-token raw units.
feeuint256Protocol fee in six-decimal USDC units.
backinguint256Reference-valued collateral in six-decimal USDC units.
outputuint256Validated output amount in output-token raw units.
routeuint256External vault ID, or zero for liquid collateral.

redeem

Burn QEURO and pay the user, fees and execution spread.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function redeem(address recipient, uint256 input, uint256 backing, uint256 output, uint256 fee) external;

Parameters

NameTypeDescription
recipientaddressAddress receiving the output transfer.
inputuint256Gross input amount in input-token raw units.
backinguint256Reference-valued collateral in six-decimal USDC units.
outputuint256Validated output amount in output-token raw units.
feeuint256Protocol fee in six-decimal USDC units.

_fees

function _fees(ITransferVault v, IERC20 token, uint256 fee, string memory source) private;

deploy

Deposit backing into the configured external adapter.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function deploy(uint256 id, uint256 amount) external;

Parameters

NameTypeDescription
iduint256External vault identifier.
amountuint256Amount in the token units of the selected operation.

_deploy

function _deploy(ITransferVault v, IERC20 token, uint256 id, uint256 amount) private;

Events

UsdcDeployedToExternalVault

event UsdcDeployedToExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalAfter);

IYieldSettlementView

Git Source

Functions

qeuro

Read the configured QEURO token address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function qeuro() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

usdc

Read the configured collateral token address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

oracle

Read the consumer's governed oracle address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function oracle() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

hedgerPool

Read the configured hedger accounting pool.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function hedgerPool() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

executionPricing

Read the configured execution module address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function executionPricing() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

stQEUROTokenByVaultId

Read the stQEURO recipient for an external vault.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function stQEUROTokenByVaultId(uint256) external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

mintFee

Read the mint fee rate in 1e18 precision.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function mintFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

minCollateralizationRatioForMinting

Read the required mint collateralization ratio.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function minCollateralizationRatioForMinting() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

criticalCollateralizationRatio

Read the liquidation threshold.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function criticalCollateralizationRatio() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

devModeEnabled

Read whether the delayed development policy is enabled.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function devModeEnabled() external view returns (bool);

Returns

NameTypeDescription
<none>boolValue defined by this accessor or calculation.

getTotalUsdcAvailable

Read loss-aware collateral available to the vault.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function getTotalUsdcAvailable() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

VaultYieldSettlementLibrary

Git Source

Linked yield validation and token interactions, retaining principal and share accounting.

Functions

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

prepare

Validate staking recipients, reference pricing and projected yield collateralization.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function prepare(uint256 id, uint256 amount, uint256 cached, uint256 lastBlock) external returns (Credit memory c);

Parameters

NameTypeDescription
iduint256External vault identifier.
amountuint256Amount in the token units of the selected operation.
cacheduint256Previous cached EUR/USD reference in 1e18 precision.
lastBlockuint256Block of the previous reference-cache update.

Returns

NameTypeDescription
cCreditValidated staking-yield credit.

prepareMint

Validate reference price, eligibility, output and projected mint collateralization.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function prepareMint(uint256 amount, uint256 minimum, uint256 cached, uint256 lastBlock)
    external
    returns (Mint memory m);

Parameters

NameTypeDescription
amountuint256Amount in the token units of the selected operation.
minimumuint256Minimum acceptable output in the output token's raw units.
cacheduint256Previous cached EUR/USD reference in 1e18 precision.
lastBlockuint256Block of the previous reference-cache update.

Returns

NameTypeDescription
mMintValidated mint fee, backing, output and reference price.

commit

Synchronize hedger accounting and mint the validated yield credit to stQEURO.

Invoked through the consumer; delegatecall retains its storage and original sender.

Notes:

  • security: Consumer permissions and accounting checks remain in force.

  • validation: Applies the selected operation's bounds; failures revert the entire call.

  • state-changes: Updates the calling consumer and downstream contracts as described above.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: The consuming operation retains its existing reentrancy guards.

  • access: Consumer entrypoint permissions; this helper grants no additional authority.

  • oracle: Uses the consumer's configured reference and execution paths where the operation requires pricing.

function commit(uint256 amount, Credit memory c) external;

Parameters

NameTypeDescription
amountuint256Amount in the token units of the selected operation.
cCreditValidated yield credit with output, backing, price and recipient.

Structs

Credit

struct Credit {
    uint256 quantity;
    uint256 backing;
    uint256 price;
    address recipient;
}

Mint

struct Mint {
    uint256 fee;
    uint256 backing;
    uint256 quantity;
    uint256 price;
}

YieldShiftCalculationLibrary

Git Source

Title: YieldShiftCalculationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Calculation functions for YieldShift to reduce contract size

Extracted from YieldShift to reduce bytecode size

Note: security-contact: team@quantillon.money

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

calculateOptimalYieldShift

Calculates optimal yield shift based on pool ratio

Calculates optimal yield shift to balance user and hedger pools

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateOptimalYieldShift(
    uint256 poolRatio,
    uint256 baseYieldShift,
    uint256 maxYieldShift,
    uint256 targetPoolRatio
) external pure returns (uint256 optimalShift);

Parameters

NameTypeDescription
poolRatiouint256Current pool ratio (user/hedger)
baseYieldShiftuint256Base yield shift percentage
maxYieldShiftuint256Maximum yield shift percentage
targetPoolRatiouint256Target pool ratio

Returns

NameTypeDescription
optimalShiftuint256Optimal yield shift percentage

applyGradualAdjustment

Applies gradual adjustment to yield shift

Gradually adjusts yield shift to prevent sudden changes

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function applyGradualAdjustment(uint256 currentShift, uint256 targetShift, uint256 adjustmentSpeed)
    external
    pure
    returns (uint256 newShift);

Parameters

NameTypeDescription
currentShiftuint256Current yield shift
targetShiftuint256Target yield shift
adjustmentSpeeduint256Adjustment speed (basis points per update)

Returns

NameTypeDescription
newShiftuint256New yield shift after adjustment

YieldShiftOptimizationLibrary

Git Source

Title: YieldShiftOptimizationLibrary

Author: Quantillon Labs

Library for YieldShift pool metrics, historical data, and utility functions

Extracts utility functions from YieldShift to reduce contract size

Constants

MIN_HOLDING_PERIOD

uint256 public constant MIN_HOLDING_PERIOD = 7 days

TWAP_PERIOD

uint256 public constant TWAP_PERIOD = 24 hours

MAX_TIME_ELAPSED

uint256 public constant MAX_TIME_ELAPSED = 365 days

MAX_HISTORY_LENGTH

uint256 public constant MAX_HISTORY_LENGTH = 100

Functions

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

getCurrentPoolMetrics

Get current pool metrics

Returns current pool sizes and ratio for yield shift calculations

Notes:

  • security: No security implications - view function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Reverts when a configured pool metric integration fails

  • reentrancy: Not applicable - view function

  • access: Public function

  • oracle: No oracle dependencies

function getCurrentPoolMetrics(address userPoolAddress, address hedgerPoolAddress)
    external
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio);

Parameters

NameTypeDescription
userPoolAddressaddressAddress of the user pool contract
hedgerPoolAddressaddressAddress of the hedger pool contract

Returns

NameTypeDescription
userPoolSizeuint256Current user pool size
hedgerPoolSizeuint256Current hedger pool size
poolRatiouint256Ratio of user to hedger pool sizes

getEligiblePoolMetrics

Get eligible pool metrics that only count deposits meeting holding period requirements

SECURITY: Prevents flash deposit attacks by excluding recent deposits from yield calculations

Notes:

  • security: Prevents flash deposit attacks by excluding recent deposits

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Reverts when a configured pool metric integration fails

  • reentrancy: Not applicable - view function

  • access: Public function

  • oracle: No oracle dependencies

function getEligiblePoolMetrics(
    address userPoolAddress,
    address hedgerPoolAddress,
    uint256 currentTime,
    uint256 lastUpdateTime
) external view returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio);

Parameters

NameTypeDescription
userPoolAddressaddressAddress of the user pool contract
hedgerPoolAddressaddressAddress of the hedger pool contract
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
userPoolSizeuint256Eligible user pool size (deposits older than MIN_HOLDING_PERIOD)
hedgerPoolSizeuint256Eligible hedger pool size (deposits older than MIN_HOLDING_PERIOD)
poolRatiouint256Ratio of eligible pool sizes

_calculateEligibleUserPoolSize

Internal function to calculate eligible user pool size

Only counts deposits older than MIN_HOLDING_PERIOD

Notes:

  • security: Prevents flash deposit attacks by excluding recent deposits

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateEligibleUserPoolSize(uint256 totalUserPoolSize, uint256 currentTime, uint256 lastUpdateTime)
    internal
    pure
    returns (uint256 eligibleSize);

Parameters

NameTypeDescription
totalUserPoolSizeuint256Current total user pool size
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
eligibleSizeuint256Eligible pool size for yield calculations

_calculateEligibleHedgerPoolSize

Internal function to calculate eligible hedger pool size

Only counts deposits older than MIN_HOLDING_PERIOD

Notes:

  • security: Prevents flash deposit attacks by excluding recent deposits

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateEligibleHedgerPoolSize(uint256 totalHedgerPoolSize, uint256 currentTime, uint256 lastUpdateTime)
    internal
    pure
    returns (uint256 eligibleSize);

Parameters

NameTypeDescription
totalHedgerPoolSizeuint256Current total hedger pool size
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
eligibleSizeuint256Eligible pool size for yield calculations

_calculateHoldingPeriodDiscount

Internal function to calculate holding period discount

Returns a percentage (in basis points) representing eligible deposits

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling function

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Internal function

  • oracle: No oracle dependencies

function _calculateHoldingPeriodDiscount(uint256 currentTime, uint256 lastUpdateTime)
    internal
    pure
    returns (uint256 discountBps);

Parameters

NameTypeDescription
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
discountBpsuint256Discount in basis points (10000 = 100%)

getTimeWeightedAverage

Get time weighted average of pool history

Calculates time weighted average of pool history over a specified period

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function getTimeWeightedAverage(
    PoolSnapshot[] memory poolHistory,
    uint256 period,
    bool isUserPool,
    uint256 currentTime
) external pure returns (uint256);

Parameters

NameTypeDescription
poolHistoryPoolSnapshot[]Array of pool snapshots
perioduint256Time period for calculation
isUserPoolboolWhether this is for user pool or hedger pool
currentTimeuint256Current timestamp

Returns

NameTypeDescription
<none>uint256Time weighted average value

addToPoolHistory

Add pool snapshot to history

Adds a pool snapshot to the history array with size management

Notes:

  • security: No security implications - pure function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function addToPoolHistory(PoolSnapshot[] memory poolHistory, uint256 poolSize, bool isUserPool, uint256 currentTime)
    external
    pure
    returns (PoolSnapshot[] memory newHistory);

Parameters

NameTypeDescription
poolHistoryPoolSnapshot[]Array of pool snapshots to add to
poolSizeuint256Size of the pool to record
isUserPoolboolWhether this is for user pool or hedger pool
currentTimeuint256Current timestamp

Returns

NameTypeDescription
newHistoryPoolSnapshot[]Updated pool history array

calculateUserAllocation

Calculate user allocation from current yield shift

Calculates user allocation based on current yield shift percentage

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateUserAllocation(uint256 userYieldPool, uint256 hedgerYieldPool, uint256 currentYieldShift)
    external
    pure
    returns (uint256);

Parameters

NameTypeDescription
userYieldPooluint256Current user yield pool amount
hedgerYieldPooluint256Current hedger yield pool amount
currentYieldShiftuint256Current yield shift percentage

Returns

NameTypeDescription
<none>uint256User allocation amount based on current yield shift percentage

calculateHedgerAllocation

Calculate hedger allocation from current yield shift

Calculates hedger allocation based on current yield shift percentage

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateHedgerAllocation(uint256 userYieldPool, uint256 hedgerYieldPool, uint256 currentYieldShift)
    external
    pure
    returns (uint256);

Parameters

NameTypeDescription
userYieldPooluint256Current user yield pool amount
hedgerYieldPooluint256Current hedger yield pool amount
currentYieldShiftuint256Current yield shift percentage

Returns

NameTypeDescription
<none>uint256Hedger allocation amount based on current yield shift percentage

isWithinTolerance

Check if a value is within tolerance of a target value

Checks if a value is within the specified tolerance of a target

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function isWithinTolerance(uint256 value, uint256 target, uint256 toleranceBps) external pure returns (bool);

Parameters

NameTypeDescription
valueuint256The value to check
targetuint256The target value
toleranceBpsuint256Tolerance in basis points (e.g., 1000 = 10%)

Returns

NameTypeDescription
<none>boolTrue if value is within tolerance, false otherwise

calculateHistoricalYieldShift

Calculate historical yield shift metrics

Calculates statistical metrics for yield shift history

Notes:

  • security: No security implications - pure calculation function

  • validation: Input validation handled by calling contract

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - pure function

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function calculateHistoricalYieldShift(
    YieldShiftSnapshot[] memory yieldShiftHistory,
    uint256 period,
    uint256 currentTime
) external pure returns (uint256 averageShift, uint256 maxShift, uint256 minShift, uint256 volatility);

Parameters

NameTypeDescription
yieldShiftHistoryYieldShiftSnapshot[]Array of yield shift snapshots
perioduint256Time period to analyze
currentTimeuint256Current timestamp

Returns

NameTypeDescription
averageShiftuint256Average yield shift during the period
maxShiftuint256Maximum yield shift during the period
minShiftuint256Minimum yield shift during the period
volatilityuint256Volatility measure of yield shifts

Structs

PoolSnapshot

struct PoolSnapshot {
    uint64 timestamp;
    uint128 userPoolSize;
    uint128 hedgerPoolSize;
}

YieldShiftSnapshot

struct YieldShiftSnapshot {
    uint128 yieldShift;
    uint64 timestamp;
}

YieldValidationLibrary

Git Source

Title: YieldValidationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Yield-specific validation functions for Quantillon Protocol

Main characteristics:

  • Validation functions specific to yield operations
  • Yield shift mechanism validations
  • Slippage protection validations
  • Yield distribution validations

Note: security-contact: team@quantillon.money

Constants

VERSION

Library version (semver); see deployments/{chainId}/versions.json for provenance.

string internal constant VERSION = "1.0.0"

Functions

validateYieldShift

Validates yield shift percentage (0-100%)

Ensures yield shift is within valid range of 0-10000 basis points

Notes:

  • security: Prevents invalid yield shifts that could destabilize yield distribution

  • validation: Ensures yield shift is within valid percentage range

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidParameter if shift exceeds 100%

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateYieldShift(uint256 shift) internal pure;

Parameters

NameTypeDescription
shiftuint256The yield shift percentage to validate (in basis points)

validateAdjustmentSpeed

Validates adjustment speed for yield shift mechanisms

Prevents excessively fast adjustments that could destabilize the system

Notes:

  • security: Prevents rapid adjustments that could destabilize yield mechanisms

  • validation: Ensures adjustment speed stays within safe bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidParameter if speed exceeds maximum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateAdjustmentSpeed(uint256 speed, uint256 maxSpeed) internal pure;

Parameters

NameTypeDescription
speeduint256The adjustment speed to validate
maxSpeeduint256The maximum allowed adjustment speed

validateTargetRatio

Validates target ratio for yield distribution mechanisms

Ensures ratio is positive and within acceptable bounds

Notes:

  • security: Prevents invalid ratios that could break yield distribution

  • validation: Ensures ratio is positive and within acceptable bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidParameter or AboveLimit based on validation

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateTargetRatio(uint256 ratio, uint256 maxRatio) internal pure;

Parameters

NameTypeDescription
ratiouint256The target ratio to validate
maxRatiouint256The maximum allowed ratio

validateTreasuryAddress

Validates treasury address is not zero address

Prevents setting treasury to zero address which could cause loss of funds

Notes:

  • security: Prevents loss of funds by ensuring treasury is properly set

  • validation: Ensures treasury address is valid for fund operations

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws ZeroAddress if treasury is zero address

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateTreasuryAddress(address treasury) internal pure;

Parameters

NameTypeDescription
treasuryaddressThe treasury address to validate

Contents

MockAaveVault

Git Source

Title: MockAaveVault

Localhost-only mock that emulates a third-party Aave-like USDC vault.

Tracks principal-like balances by account and supports synthetic yield injection. Mirrors MockMorphoVault interface for symmetric adapter testing.

Constants

USDC

IERC20 public immutable USDC

State Variables

shareBalanceOf

mapping(address => uint256) public shareBalanceOf

totalShares

uint256 public totalShares

Functions

constructor

constructor(address usdc_) ;

depositUnderlying

function depositUnderlying(uint256 assets, address onBehalfOf) external returns (uint256 shares);

withdrawUnderlying

function withdrawUnderlying(uint256 assets, address to) external returns (uint256 withdrawn);

injectYield

function injectYield(uint256 amount) external;

totalAssets

function totalAssets() public view returns (uint256);

totalUnderlyingOf

function totalUnderlyingOf(address account) external view returns (uint256);

Events

Deposited

event Deposited(address indexed caller, address indexed onBehalfOf, uint256 assets);

Withdrawn

event Withdrawn(address indexed caller, address indexed to, uint256 assets);

YieldInjected

event YieldInjected(address indexed from, uint256 amount);

MockAggregatorV3

Git Source

Inherits: AggregatorV3Interface

Title: MockAggregatorV3

Mock Chainlink price feed for testing

Implements AggregatorV3Interface with configurable behavior to simulate:

  • Price updates with variable decimals
  • Revert scenarios and invalid price outputs
  • Stale timestamps and round progression

Note: security-contact: team@quantillon.money

State Variables

price

int256 public price

decimals_

uint8 public decimals_

updatedAt

uint256 public updatedAt

shouldRevert

bool public shouldRevert

shouldReturnInvalidPrice

bool public shouldReturnInvalidPrice

roundId

uint80 public roundId = 1

Functions

constructor

Constructor for MockPriceFeed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: Initializes decimals and updatedAt timestamp

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

constructor(uint8 _decimals) ;

Parameters

NameTypeDescription
_decimalsuint8The number of decimals for the price feed

setPrice

Sets the price for the mock price feed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: Updates price and increments roundId

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function setPrice(int256 _price) external;

Parameters

NameTypeDescription
_priceint256The price to set

setShouldRevert

Sets whether the mock price feed should revert

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: Updates shouldRevert flag

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function setShouldRevert(bool _shouldRevert) external;

Parameters

NameTypeDescription
_shouldRevertboolWhether the price feed should revert

setShouldReturnInvalidPrice

Sets whether the mock price feed should return invalid price

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: Updates shouldReturnInvalidPrice flag

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function setShouldReturnInvalidPrice(bool _shouldReturnInvalidPrice) external;

Parameters

NameTypeDescription
_shouldReturnInvalidPriceboolWhether the price feed should return invalid price

setUpdatedAt

Sets the updated timestamp for the mock price feed

Test helper function to control price feed timestamps

Notes:

  • security: No security implications - test helper function

  • validation: No input validation required - test helper

  • state-changes: Updates the updatedAt timestamp for testing

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - simple state update

  • access: Public - no access restrictions

  • oracle: No oracle dependency - mock function

function setUpdatedAt(uint256 _updatedAt) external;

Parameters

NameTypeDescription
_updatedAtuint256The timestamp to set as the last update time

latestRoundData

Returns the latest round data for the mock price feed

Mock implementation of Chainlink's latestRoundData function for testing

Notes:

  • security: No security implications - test function

  • validation: No input validation required - test function

  • state-changes: No state changes - test function

  • events: No events emitted - test function

  • errors: No errors thrown - test function

  • reentrancy: Not applicable - test function

  • access: Public - no access restrictions

  • oracle: No oracle dependency for test function

function latestRoundData()
    external
    view
    returns (uint80 _roundId, int256 _answer, uint256 _startedAt, uint256 _updatedAt, uint80 _answeredInRound);

Returns

NameTypeDescription
_roundIduint80The round ID
_answerint256The price answer
_startedAtuint256The timestamp when the round started
_updatedAtuint256The timestamp when the round was last updated
_answeredInRounduint80The round ID in which the answer was computed

getRoundData

Gets round data for the mock price feed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Throws "MockAggregator: Simulated failure" if shouldRevert is true

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function getRoundData(
    uint80 /* _id */
)
    external
    view
    returns (uint80 _roundId, int256 _answer, uint256 _startedAt, uint256 _updatedAt, uint80 _answeredInRound);

Returns

NameTypeDescription
_roundIduint80The round ID
_answerint256The price answer
_startedAtuint256The timestamp when the round started
_updatedAtuint256The timestamp when the round was updated
_answeredInRounduint80The round ID when the answer was provided

decimals

Gets the number of decimals for the mock price feed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function decimals() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8The number of decimals

description

Gets the description of the mock price feed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function description() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringThe description string

version

Gets the version of the mock price feed

Mock function for testing purposes

Notes:

  • security: No security validations - test mock

  • validation: No input validation - test mock

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - test mock

  • access: Public - test mock

  • oracle: No oracle dependencies

function version() external pure returns (uint256);

Returns

NameTypeDescription
<none>uint256The version number

MockChainlinkOracle

Git Source

Inherits: IChainlinkOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable

Title: MockChainlinkOracle

Author: Quantillon Labs

Mock oracle that implements IChainlinkOracle interface but uses mock feeds

Used for localhost testing - provides same interface as ChainlinkOracle

Constants

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

ORACLE_MANAGER_ROLE

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

MIN_EUR_USD_PRICE

uint256 public constant MIN_EUR_USD_PRICE = 0.5e18

MAX_EUR_USD_PRICE

uint256 public constant MAX_EUR_USD_PRICE = 2.0e18

MIN_USDC_USD_PRICE

uint256 public constant MIN_USDC_USD_PRICE = 0.95e18

MAX_USDC_USD_PRICE

uint256 public constant MAX_USDC_USD_PRICE = 1.05e18

MAX_PRICE_DEVIATION

uint256 public constant MAX_PRICE_DEVIATION = 500

MIN_BLOCKS_BETWEEN_UPDATES

uint256 public constant MIN_BLOCKS_BETWEEN_UPDATES = 1

State Variables

eurUsdPriceFeed

AggregatorV3Interface public eurUsdPriceFeed

usdcUsdPriceFeed

AggregatorV3Interface public usdcUsdPriceFeed

treasury

address public treasury

originalAdmin

address private originalAdmin

lastValidEurUsdPrice

uint256 public lastValidEurUsdPrice

lastValidUsdcUsdPrice

uint256 public lastValidUsdcUsdPrice

lastPriceUpdateBlock

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

bool public circuitBreakerTriggered

devModeEnabled

bool public devModeEnabled

Functions

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the mock oracle

function initialize(
    address admin,
    address _eurUsdPriceFeed,
    address _usdcUsdPriceFeed,
    address /* _treasury */
)
    external
    initializer;

Parameters

NameTypeDescription
adminaddressAdmin address
_eurUsdPriceFeedaddressMock EUR/USD feed address
_usdcUsdPriceFeedaddressMock USDC/USD feed address
<none>address

getEurUsdPrice

Gets the current EUR/USD price with validation and auto-updates lastValidEurUsdPrice

function getEurUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if price is valid and fresh

getUsdcUsdPrice

Gets the current USDC/USD price with validation

function getUsdcUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals
isValidboolTrue if price is valid and fresh

_updatePrices

Updates prices and validates them

Internal function to update and validate current prices

function _updatePrices() internal;

_calculateEurUsdPrice

Internal function to calculate EUR/USD price

Avoids external calls to prevent reentrancy

function _calculateEurUsdPrice() internal pure returns (uint256);

_calculateUsdcUsdPrice

Internal function to calculate USDC/USD price

Avoids external calls to prevent reentrancy

function _calculateUsdcUsdPrice() internal pure returns (uint256);

_scalePrice

Scales price from feed decimals to 18 decimals

function _scalePrice(int256 price, uint8 feedDecimals) internal pure returns (uint256);

Parameters

NameTypeDescription
priceint256Price from feed
feedDecimalsuint8Number of decimals in the feed

Returns

NameTypeDescription
<none>uint256Scaled price in 18 decimals

_divRound

Divides with rounding

function _divRound(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256Numerator
buint256Denominator

Returns

NameTypeDescription
<none>uint256Result with rounding

updateTreasury

Updates treasury address

Treasury can only be updated to the original admin address to prevent arbitrary sends

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

unpause

Unpauses the contract

function unpause() external onlyRole(EMERGENCY_ROLE);

recoverETH

Recovers ETH sent to the contract

Only sends ETH to the original admin address to prevent arbitrary sends

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

resetCircuitBreaker

Resets the circuit breaker

function resetCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Triggers the circuit breaker

function triggerCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

pause

Pauses the contract

function pause() external onlyRole(EMERGENCY_ROLE);

receive

receive() external payable;

getOracleHealth

Mock implementation of getOracleHealth

function getOracleHealth() external pure override returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

getEurUsdDetails

Mock implementation of getEurUsdDetails

function getEurUsdDetails()
    external
    view
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

getOracleConfig

Mock implementation of getOracleConfig

function getOracleConfig()
    external
    view
    override
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

getPriceFeedAddresses

Mock implementation of getPriceFeedAddresses

function getPriceFeedAddresses()
    external
    view
    override
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

checkPriceFeedConnectivity

Mock implementation of checkPriceFeedConnectivity

function checkPriceFeedConnectivity()
    external
    view
    override
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

updatePriceBounds

Mock implementation of updatePriceBounds

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external override onlyRole(ORACLE_MANAGER_ROLE);

updateUsdcTolerance

Mock implementation of updateUsdcTolerance

function updateUsdcTolerance(uint256 newToleranceBps) external override onlyRole(ORACLE_MANAGER_ROLE);

updatePriceFeeds

Mock implementation of updatePriceFeeds

function updatePriceFeeds(address _eurUsdFeed, address _usdcUsdFeed)
    external
    override
    onlyRole(ORACLE_MANAGER_ROLE);

recoverToken

Mock implementation of recoverToken

function recoverToken(address token, uint256 amount) external view override onlyRole(DEFAULT_ADMIN_ROLE);

setPrice

Set the EUR/USD price for testing purposes

Only available in mock oracle for testing

function setPrice(uint256 _price) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_priceuint256The new EUR/USD price in 18 decimals

setUsdcUsdPrice

Set the USDC/USD price for testing purposes

Only available in mock oracle for testing

function setUsdcUsdPrice(uint256 _price) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_priceuint256The new USDC/USD price in 18 decimals

setPrices

Set both EUR/USD and USDC/USD prices for testing purposes

Only available in mock oracle for testing

function setPrices(uint256 _eurUsdPrice, uint256 _usdcUsdPrice) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_eurUsdPriceuint256The new EUR/USD price in 18 decimals
_usdcUsdPriceuint256The new USDC/USD price in 18 decimals

setUpdatedAt

Set the updated timestamp for testing purposes

Only available in mock oracle for testing

function setUpdatedAt(uint256 _updatedAt) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_updatedAtuint256The new timestamp

setDevMode

Toggles dev mode to disable spread deviation checks

DEV ONLY: When enabled, price deviation checks are skipped for testing

function setDevMode(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable dev mode, false to disable

Events

PriceDeviationDetected

event PriceDeviationDetected(uint256 newPrice, uint256 lastPrice, uint256 deviationBps, uint256 blockNumber);

CircuitBreakerTriggered

event CircuitBreakerTriggered(uint256 blockNumber, string reason);

CircuitBreakerReset

event CircuitBreakerReset(uint256 blockNumber);

ETHRecovered

event ETHRecovered(address indexed treasury, uint256 amount);

DevModeToggled

event DevModeToggled(bool enabled, address indexed caller);

MockMorphoVault

Git Source

Title: MockMorphoVault

Localhost-only mock that emulates a third-party Morpho-like USDC vault.

Tracks principal-like balances by account and supports synthetic yield injection.

Constants

USDC

IERC20 public immutable USDC

State Variables

shareBalanceOf

mapping(address => uint256) public shareBalanceOf

totalShares

uint256 public totalShares

Functions

constructor

constructor(address usdc_) ;

depositUnderlying

function depositUnderlying(uint256 assets, address onBehalfOf) external returns (uint256 shares);

withdrawUnderlying

function withdrawUnderlying(uint256 assets, address to) external returns (uint256 withdrawn);

injectYield

function injectYield(uint256 amount) external;

totalAssets

function totalAssets() public view returns (uint256);

totalUnderlyingOf

function totalUnderlyingOf(address account) external view returns (uint256);

Events

Deposited

event Deposited(address indexed caller, address indexed onBehalfOf, uint256 assets);

Withdrawn

event Withdrawn(address indexed caller, address indexed to, uint256 assets);

YieldInjected

event YieldInjected(address indexed from, uint256 amount);

MockStorkOracle

Git Source

Inherits: IStorkOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable

Title: MockStorkOracle

Author: Quantillon Labs

Mock oracle that implements IStorkOracle interface but uses mock data

Used for localhost testing - provides same interface as StorkOracle

Constants

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

ORACLE_MANAGER_ROLE

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

MIN_EUR_USD_PRICE

uint256 public constant MIN_EUR_USD_PRICE = 0.5e18

MAX_EUR_USD_PRICE

uint256 public constant MAX_EUR_USD_PRICE = 2.0e18

MIN_USDC_USD_PRICE

uint256 public constant MIN_USDC_USD_PRICE = 0.95e18

MAX_USDC_USD_PRICE

uint256 public constant MAX_USDC_USD_PRICE = 1.05e18

MAX_PRICE_DEVIATION

uint256 public constant MAX_PRICE_DEVIATION = 500

MIN_BLOCKS_BETWEEN_UPDATES

uint256 public constant MIN_BLOCKS_BETWEEN_UPDATES = 1

State Variables

treasury

address public treasury

originalAdmin

address private originalAdmin

lastValidEurUsdPrice

uint256 public lastValidEurUsdPrice

lastValidUsdcUsdPrice

uint256 public lastValidUsdcUsdPrice

lastPriceUpdateBlock

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

bool public circuitBreakerTriggered

devModeEnabled

bool public devModeEnabled

Functions

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the mock oracle

function initialize(
    address admin,
    address _storkFeedAddress,
    bytes32 _eurUsdFeedId,
    bytes32 _usdcUsdFeedId,
    address _treasury
) external initializer;

Parameters

NameTypeDescription
adminaddressAdmin address
_storkFeedAddressaddressMock Stork feed address (unused, kept for interface compatibility)
_eurUsdFeedIdbytes32Mock EUR/USD feed ID (unused, kept for interface compatibility)
_usdcUsdFeedIdbytes32Mock USDC/USD feed ID (unused, kept for interface compatibility)
_treasuryaddressTreasury address

getEurUsdPrice

Gets the current EUR/USD price with validation

function getEurUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if price is valid and fresh

getUsdcUsdPrice

Gets the current USDC/USD price with validation

function getUsdcUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals
isValidboolTrue if price is valid and fresh

updateTreasury

Updates treasury address

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

unpause

Unpauses the contract

function unpause() external onlyRole(EMERGENCY_ROLE);

recoverETH

Recovers ETH sent to the contract

Only sends ETH to the original admin address to prevent arbitrary sends

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

resetCircuitBreaker

Resets the circuit breaker

function resetCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Triggers the circuit breaker

function triggerCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

pause

Pauses the contract

function pause() external onlyRole(EMERGENCY_ROLE);

receive

receive() external payable;

getOracleHealth

Mock implementation of getOracleHealth

function getOracleHealth() external view override returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

getEurUsdDetails

Mock implementation of getEurUsdDetails

function getEurUsdDetails()
    external
    view
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

getOracleConfig

Mock implementation of getOracleConfig

function getOracleConfig()
    external
    view
    override
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

getPriceFeedAddresses

Mock implementation of getPriceFeedAddresses

function getPriceFeedAddresses()
    external
    view
    override
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

checkPriceFeedConnectivity

Mock implementation of checkPriceFeedConnectivity

function checkPriceFeedConnectivity()
    external
    view
    override
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

updatePriceBounds

Mock implementation of updatePriceBounds

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external override onlyRole(ORACLE_MANAGER_ROLE);

updateUsdcTolerance

Mock implementation of updateUsdcTolerance

function updateUsdcTolerance(uint256 newToleranceBps) external override onlyRole(ORACLE_MANAGER_ROLE);

updatePriceFeeds

Mock implementation of updatePriceFeeds

function updatePriceFeeds(address _storkFeedAddress, bytes32 _eurUsdFeedId, bytes32 _usdcUsdFeedId)
    external
    view
    override
    onlyRole(ORACLE_MANAGER_ROLE);

recoverToken

Mock implementation of recoverToken

function recoverToken(address token, uint256 amount) external view override onlyRole(DEFAULT_ADMIN_ROLE);

setPrice

Set the EUR/USD price for testing purposes

Only available in mock oracle for testing

function setPrice(uint256 _price) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_priceuint256The new EUR/USD price in 18 decimals

setUsdcUsdPrice

Set the USDC/USD price for testing purposes

Only available in mock oracle for testing

function setUsdcUsdPrice(uint256 _price) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_priceuint256The new USDC/USD price in 18 decimals

setPrices

Set both EUR/USD and USDC/USD prices for testing purposes

Only available in mock oracle for testing

function setPrices(uint256 _eurUsdPrice, uint256 _usdcUsdPrice) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_eurUsdPriceuint256The new EUR/USD price in 18 decimals
_usdcUsdPriceuint256The new USDC/USD price in 18 decimals

setDevMode

Toggles dev mode to disable spread deviation checks

DEV ONLY: When enabled, price deviation checks are skipped for testing

function setDevMode(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable dev mode, false to disable

Events

PriceDeviationDetected

event PriceDeviationDetected(uint256 newPrice, uint256 lastPrice, uint256 deviationBps, uint256 blockNumber);

CircuitBreakerTriggered

event CircuitBreakerTriggered(uint256 blockNumber, string reason);

CircuitBreakerReset

event CircuitBreakerReset(uint256 blockNumber);

ETHRecovered

event ETHRecovered(address indexed treasury, uint256 amount);

DevModeToggled

event DevModeToggled(bool enabled, address indexed caller);

MockUSDC

Git Source

Inherits: ERC20, Ownable

Title: MockUSDC

This is a simplified ERC20 token that mimics USDC behavior

Mock USDC token for testing and development

Constants

_DECIMALS

uint8 private constant _DECIMALS = 6

Functions

constructor

constructor() ERC20("USD Coin", "USDC") Ownable(msg.sender);

decimals

Returns the number of decimals used to get its user representation.

function decimals() public pure override returns (uint8);

mint

Mint tokens to a specific address (for testing)

function mint(address to, uint256 amount) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to mint tokens to
amountuint256The amount of tokens to mint

faucet

Faucet function for easy testing - anyone can call this (max 100k USDC per call)

function faucet(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256The amount of tokens to mint to caller

Contents

ChainlinkOracle

Git Source

Inherits: IChainlinkOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: ChainlinkOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

EUR/USD and USDC/USD price manager for Quantillon Protocol

Key features:

  • Fetch EUR/USD price from Chainlink
  • Validate USDC/USD (should remain close to $1.00)
  • Circuit breakers against outlier prices
  • Fallbacks in case of oracle outage
  • Data freshness checks

Note: security-contact: team@quantillon.money

Constants

ORACLE_MANAGER_ROLE

Role to manage oracle configurations

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency actions

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for contract upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_PRICE_STALENESS

Maximum duration before the EUR/USD price is considered stale (2 hours)

7200 seconds gives the primary FX feed limited heartbeat headroom while keeping mint/redeem pricing fresh.

uint256 public constant MAX_PRICE_STALENESS = 2 hours

MAX_USDC_PRICE_STALENESS

Maximum duration before the USDC/USD price is considered stale (25 hours)

Chainlink stablecoin feeds often refresh on a daily heartbeat; this is slightly above that cadence.

uint256 public constant MAX_USDC_PRICE_STALENESS = 25 hours

MAX_PRICE_DEVIATION

Maximum allowed deviation from previous price (5%)

500 basis points = 5% in basis points (500/10000)

uint256 public constant MAX_PRICE_DEVIATION = 500

BASIS_POINTS

Basis for basis points calculations

uint256 public constant BASIS_POINTS = 10000

MAX_TIMESTAMP_DRIFT

Maximum timestamp drift tolerance (15 minutes)

Prevents timestamp manipulation attacks by miners

uint256 public constant MAX_TIMESTAMP_DRIFT = 900

DEV_MODE_DELAY

Minimum delay before a proposed dev-mode change takes effect

uint256 public constant DEV_MODE_DELAY = 48 hours

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

State Variables

eurUsdPriceFeed

Interface to Chainlink EUR/USD price feed

AggregatorV3Interface public eurUsdPriceFeed

usdcUsdPriceFeed

Interface to Chainlink USDC/USD price feed

Used for USDC price validation and cross-checking

Should be the official USDC/USD Chainlink feed

AggregatorV3Interface public usdcUsdPriceFeed

sequencerUptimeFeed

Optional Chainlink L2 sequencer uptime feed (Base/Arbitrum/etc)

Set to address(0) on L1 (check skipped). On Base set to the Chainlink sequencer feed.

AggregatorV3Interface public sequencerUptimeFeed

sequencerGracePeriod

Grace period after sequencer restart before prices are trusted again

Recommended: 3600 seconds (1 hour) to allow stale data to flush

uint256 public sequencerGracePeriod

treasury

Treasury address for ETH recovery

SECURITY: Only this address can receive ETH from recoverETH function

address public treasury

minEurUsdPrice

Minimum accepted EUR/USD price (lower circuit breaker)

Initialized to 0.80 USD per EUR (extreme crisis)

uint256 public minEurUsdPrice

maxEurUsdPrice

Maximum accepted EUR/USD price (upper circuit breaker)

Initialized to 1.40 USD per EUR (extreme scenario)

uint256 public maxEurUsdPrice

lastValidEurUsdPrice

Last valid EUR/USD price recorded (18 decimals)

Used as fallback if oracle is down

uint256 public lastValidEurUsdPrice

lastPriceUpdateTime

Timestamp of the last valid price update

uint256 public lastPriceUpdateTime

lastPriceUpdateBlock

Block number of the last valid price update

Used for block-based staleness checks to prevent timestamp manipulation

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

Circuit breaker status (true = triggered, fixed prices)

bool public circuitBreakerTriggered

usdcToleranceBps

USDC/USD tolerance (USDC should remain close to $1.00)

200 basis points = 2% (USDC can vary between 0.98 and 1.02)

uint256 public usdcToleranceBps

devModeEnabled

Dev mode flag to disable spread deviation checks

When enabled, price deviation checks are skipped (dev/testing only)

bool public devModeEnabled

pendingDevMode

Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

Timestamp at which pendingDevMode may be applied (0 = no pending proposal)

uint256 public devModePendingAt

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructor for ChainlinkOracle contract

Initializes the TimeProvider and disables initializers for proxy pattern

Notes:

  • security: Validates TimeProvider address is not zero

  • validation: Validates _TIME_PROVIDER is not address(0)

  • state-changes: Sets TIME_PROVIDER immutable variable and disables initializers

  • events: No events emitted

  • errors: Throws "Zero address" if _TIME_PROVIDER is address(0)

  • reentrancy: Not applicable - constructor

  • access: Public - anyone can deploy

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the TimeProvider contract for centralized time management

initialize

Initializes the oracle contract with Chainlink price feeds

Sets up all core dependencies, roles, and default configuration parameters

Notes:

  • security: Validates all addresses are not zero, grants admin roles

  • validation: Validates all input addresses are not address(0)

  • state-changes: Initializes all state variables, sets default price bounds

  • events: Emits PriceUpdated during initial price update

  • errors: Throws "Oracle: Admin cannot be zero" if admin is address(0)

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during deployment

  • oracle: Initializes Chainlink price feed interfaces

function initialize(address admin, address _eurUsdPriceFeed, address _usdcUsdPriceFeed, address _treasury)
    public
    initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_eurUsdPriceFeedaddressChainlink EUR/USD price feed address on Base
_usdcUsdPriceFeedaddressChainlink USDC/USD price feed address on Base
_treasuryaddressTreasury address for ETH recovery

updateTreasury

Update treasury address

SECURITY: Only admin can update treasury address

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

unpause

Removes pause and resumes oracle operations

Allows emergency role to unpause the oracle after resolving issues

Notes:

  • security: Validates emergency role authorization

  • validation: No input validation required

  • state-changes: Removes pause state, resumes oracle operations

  • events: Emits Unpaused event from OpenZeppelin

  • errors: No errors thrown - safe unpause operation

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies for unpause

function unpause() external onlyRole(EMERGENCY_ROLE);

_divRound

Performs division with proper rounding to nearest integer

Adds half the divisor before division to achieve proper rounding

Notes:

  • security: Validates denominator is not zero to prevent division by zero

  • validation: Validates b > 0

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws "Oracle: Division by zero" if b is 0

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _divRound(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256Numerator
buint256Denominator

Returns

NameTypeDescription
<none>uint256Result of division with rounding to nearest

_validateTimestamp

Validates if a timestamp is recent enough to prevent manipulation attacks

Checks timestamp is not in future and not too old beyond staleness + drift limits

Notes:

  • security: Validates timestamp is not in future and within acceptable age

  • validation: Validates reportedTime <= currentTime and within MAX_PRICE_STALENESS + MAX_TIMESTAMP_DRIFT

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies for timestamp validation

function _validateTimestamp(uint256 reportedTime) internal view returns (bool);

Parameters

NameTypeDescription
reportedTimeuint256The timestamp to validate

Returns

NameTypeDescription
<none>booltrue if the timestamp is valid, false otherwise

_validateTimestampWithMaxAge

Validates a feed timestamp against a caller-selected maximum age.

Rejects future-dated timestamps and timestamps older than maxStaleness + MAX_TIMESTAMP_DRIFT.

Notes:

  • security: Validates timestamp is not in future and within acceptable age.

  • validation: Validates reportedTime <= currentTime and within maxStaleness + MAX_TIMESTAMP_DRIFT.

  • state-changes: No state changes - view function.

  • events: No events emitted.

  • errors: No errors thrown - safe view function.

  • reentrancy: Not applicable - view function.

  • access: Internal function - no access restrictions.

  • oracle: No oracle dependencies for timestamp validation.

function _validateTimestampWithMaxAge(uint256 reportedTime, uint256 maxStaleness) internal view returns (bool);

Parameters

NameTypeDescription
reportedTimeuint256Timestamp reported by the feed.
maxStalenessuint256Maximum accepted age before drift tolerance.

Returns

NameTypeDescription
<none>booltrue if the timestamp is valid, false otherwise.

_validateEurUsdPriceData

Validates a raw EUR/USD feed value against freshness, bounds, and deviation policy.

Checks freshness via _validateTimestamp, scales the raw price, enforces the [minEurUsdPrice, maxEurUsdPrice] band, and (unless devModeEnabled) rejects a price deviating more than MAX_PRICE_DEVIATION bps from lastValidEurUsdPrice.

Notes:

  • security: Enforces staleness, circuit-breaker bounds, and deviation limits before acceptance.

  • validation: Returns isValid=false on stale, non-positive, out-of-bounds, or over-deviation input.

  • state-changes: None - view function.

  • events: None.

  • errors: None - signals failure via the (0, false) return.

  • reentrancy: Not applicable - view function.

  • access: Internal - no access restrictions.

  • oracle: Reads cached bounds/baseline; does not call external feeds.

function _validateEurUsdPriceData(int256 rawPrice, uint256 updatedAt, uint8 feedDecimals)
    internal
    view
    returns (uint256 price, bool isValid);

Parameters

NameTypeDescription
rawPriceint256Raw EUR/USD price from the feed.
updatedAtuint256Feed update timestamp.
feedDecimalsuint8Number of decimals used by the feed.

Returns

NameTypeDescription
priceuint256Scaled EUR/USD price, or 0 if validation fails before scaling.
isValidboolTrue when the price can be accepted as the next oracle baseline.

_normalizeUsdcUsdPrice

Normalizes USDC/USD for PriceUpdated events, falling back to $1.00 if invalid.

Returns $1.00 (1e18) unless the feed value is fresh (within MAX_USDC_PRICE_STALENESS), positive, and within usdcToleranceBps of $1.00, in which case the scaled price is returned.

Notes:

  • security: Bounds USDC to a tolerance band so a depegged/stale USDC feed cannot distort events.

  • validation: Falls back to 1e18 on stale, non-positive, or out-of-tolerance input.

  • state-changes: None - view function.

  • events: None.

  • errors: None - falls back to 1e18.

  • reentrancy: Not applicable - view function.

  • access: Internal - no access restrictions.

  • oracle: Used only to enrich PriceUpdated events; does not gate EUR/USD reads.

function _normalizeUsdcUsdPrice(int256 rawPrice, uint256 updatedAt, uint8 feedDecimals)
    internal
    view
    returns (uint256 usdcUsdPrice);

Parameters

NameTypeDescription
rawPriceint256Raw USDC/USD price from the feed.
updatedAtuint256Feed update timestamp.
feedDecimalsuint8Number of decimals used by the feed.

Returns

NameTypeDescription
usdcUsdPriceuint256Normalized USDC/USD price (18 decimals); $1.00 on any failure.

_readUsdcUsdPriceForEvent

Reads USDC/USD for update events without making EUR/USD reads depend on USDC health.

try/catch reads usdcUsdPriceFeed.latestRoundData()/decimals(); returns $1.00 if the round is inconsistent or any call reverts, otherwise delegates to _normalizeUsdcUsdPrice. Decoupled so a failing USDC feed can never block an EUR/USD read.

Notes:

  • security: Isolates USDC-feed failures from the EUR/USD path via try/catch.

  • validation: Rejects inconsistent rounds (roundId != answeredInRound, startedAt > updatedAt).

  • state-changes: None - view function.

  • events: None.

  • errors: None - all failures fall back to 1e18.

  • reentrancy: Not applicable - view function (external staticcall only).

  • access: Internal - no access restrictions.

  • oracle: Reads the USDC/USD Chainlink feed; result used only for events.

function _readUsdcUsdPriceForEvent() internal view returns (uint256 usdcUsdPrice);

Returns

NameTypeDescription
usdcUsdPriceuint256USDC/USD price (18 decimals) for event enrichment; $1.00 on any failure.

_commitEurUsdPrice

Commits an accepted EUR/USD price as the new oracle deviation baseline.

Stores the accepted EUR/USD price as the new baseline, records update time/block, and emits PriceUpdated. Called only after a value passes _validateEurUsdPriceData.

Notes:

  • security: Reached only after validation; advances the deviation baseline used by later reads.

  • validation: Assumes the caller validated the price; performs no checks itself.

  • state-changes: Sets lastValidEurUsdPrice, lastPriceUpdateTime, lastPriceUpdateBlock.

  • events: Emits PriceUpdated(eurUsdPrice, usdcUsdPrice, timestamp).

  • errors: None.

  • reentrancy: Not applicable - no external calls.

  • access: Internal - no access restrictions.

  • oracle: Updates the cached oracle baseline; does not call external feeds.

function _commitEurUsdPrice(uint256 eurUsdPrice, uint256 usdcUsdPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Accepted EUR/USD price to store as the new baseline (18 decimals).
usdcUsdPriceuint256USDC/USD price included in the emitted event (18 decimals).

_updatePrices

Updates and validates internal prices

Internal function called during initialization and resets, fetches fresh prices from Chainlink

Notes:

  • security: Validates price data integrity, circuit breaker bounds, and deviation limits

  • validation: Validates roundId == answeredInRound, startedAt <= updatedAt, price > 0

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateTime, lastPriceUpdateBlock

  • events: Emits PriceUpdated with current prices or CircuitBreakerTriggered if invalid

  • errors: Throws "EUR/USD price data is stale" if roundId != answeredInRound

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: Fetches fresh prices from Chainlink EUR/USD and USDC/USD feeds

function _updatePrices() internal;

_scalePrice

Scale price to 18 decimals for consistency

Converts Chainlink price from its native decimals to 18 decimals with proper rounding

Notes:

  • security: Validates rawPrice > 0 and handles decimal conversion safely

  • validation: Validates rawPrice > 0, returns 0 if invalid

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies for price scaling

function _scalePrice(int256 rawPrice, uint8 decimals) internal pure returns (uint256);

Parameters

NameTypeDescription
rawPriceint256Raw price from Chainlink
decimalsuint8Number of decimals in raw price

Returns

NameTypeDescription
<none>uint256Scaled price with 18 decimals

getOracleHealth

Retrieves the oracle global health status

Checks freshness of both price feeds and overall system health

Notes:

  • security: Validates price feed connectivity and data integrity

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function with try/catch

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check oracle health

  • oracle: Checks connectivity to Chainlink EUR/USD and USDC/USD feeds

function getOracleHealth() external view returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthybooltrue if everything operates normally
eurUsdFreshbooltrue if EUR/USD price is fresh
usdcUsdFreshbooltrue if USDC/USD price is fresh

getEurUsdDetails

Retrieves detailed information about the EUR/USD price

Provides comprehensive EUR/USD price data including staleness and bounds checks

Notes:

  • security: Validates price feed data integrity and circuit breaker status

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function with try/catch

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query EUR/USD details

  • oracle: Fetches fresh data from Chainlink EUR/USD price feed

function getEurUsdDetails()
    external
    view
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price
lastUpdateuint256Timestamp reported by the underlying EUR/USD feed
isStalebooltrue if the price is stale
withinBoundsbooltrue if within acceptable bounds

peekEurUsdPrice

Reads an independent EUR/USD reference without using the cached baseline.

Used by market-price validation and degraded redemption. The result is view-only and applies feed integrity, sequencer, freshness, positivity, and absolute-bound checks.

Notes:

  • security: Does not substitute cached prices or bypass sequencer checks.

  • validation: Rejects stale, future, malformed, nonpositive, and out-of-range data.

  • state-changes: None.

  • events: None.

  • errors: Returns false on feed failure.

  • reentrancy: Read-only feed calls.

  • access: Public.

  • oracle: Reads the configured Chainlink EUR/USD and sequencer feeds.

function peekEurUsdPrice() external view returns (uint256 price, uint256 updatedAt, bool isValid);

Returns

NameTypeDescription
priceuint256Fresh normalized EUR/USD price, or zero when invalid.
updatedAtuint256Feed timestamp.
isValidboolWhether the reference is independently valid.

getOracleConfig

Retrieves current configuration parameters

Returns all key configuration values for oracle operations

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query configuration

  • oracle: No oracle dependencies for configuration query

function getOracleConfig()
    external
    view
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum EUR/USD price
maxPriceuint256Maximum EUR/USD price
maxStalenessuint256Maximum duration before staleness
usdcToleranceuint256USDC tolerance in basis points
circuitBreakerActiveboolCircuit breaker status

getPriceFeedAddresses

Retrieves addresses of the Chainlink price feeds used

Returns feed addresses and their decimal configurations

Notes:

  • security: No security validations required - view function

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function

  • reentrancy: Not applicable - view function

  • access: Public - anyone can query feed addresses

  • oracle: Queries decimal configuration from Chainlink feeds

function getPriceFeedAddresses()
    external
    view
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD feed address
usdcUsdFeedAddressaddressUSDC/USD feed address
eurUsdDecimalsuint8Number of decimals for the EUR/USD feed
usdcUsdDecimalsuint8Number of decimals for the USDC/USD feed

checkPriceFeedConnectivity

Tests connectivity to the Chainlink price feeds

Tests if both price feeds are responding and returns latest round information

Notes:

  • security: Validates price feed connectivity and data integrity

  • validation: No input validation required - view function

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - safe view function with try/catch

  • reentrancy: Not applicable - view function

  • access: Public - anyone can test feed connectivity

  • oracle: Tests connectivity to Chainlink EUR/USD and USDC/USD feeds

function checkPriceFeedConnectivity()
    external
    view
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedbooltrue if the EUR/USD feed responds
usdcUsdConnectedbooltrue if the USDC/USD feed responds
eurUsdLatestRounduint80Latest round ID for EUR/USD
usdcUsdLatestRounduint80Latest round ID for USDC/USD

_authorizeUpgrade

Authorizes oracle contract upgrades

function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

recoverToken

Recovers tokens accidentally sent to the contract to treasury only

Emergency function to recover ERC20 tokens that are not part of normal operations

Notes:

  • security: Validates admin role and uses secure recovery library

  • validation: No input validation required - library handles validation

  • state-changes: Transfers tokens from contract to treasury

  • events: No events emitted - library handles events

  • errors: No errors thrown - library handles error cases

  • reentrancy: Not protected - library handles reentrancy

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies for token recovery

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressAddress of the token to recover
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Security considerations:

  • Only DEFAULT_ADMIN_ROLE can recover
  • Prevents sending to zero address
  • Validates balance before attempting transfer
  • Uses call() for reliable ETH transfers to any contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

resetCircuitBreaker

Resets the circuit breaker and resumes oracle usage

Emergency action after resolving an incident. Restarts price updates and disables fallback mode.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function resetCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Manually triggers the circuit breaker

Used when the team detects an issue with the oracles. Forces the use of the last known valid price.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Not applicable - no oracle dependency

function triggerCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

pause

Pauses all oracle operations

Emergency function to pause oracle in case of critical issues

Notes:

  • security: Validates emergency role authorization

  • validation: No input validation required

  • state-changes: Sets pause state, stops oracle operations

  • events: Emits Paused event from OpenZeppelin

  • errors: No errors thrown - safe pause operation

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies for pause

function pause() external onlyRole(EMERGENCY_ROLE);

getEurUsdPrice

Retrieves the current EUR/USD price with full validation

Validation process:

  1. Check circuit breaker status
  2. Fetch from Chainlink
  3. Freshness check (< 1 hour)
  4. Convert to 18 decimals
  5. Check min/max bounds
  6. Return valid price or fallback

Notes:

  • security: Validates timestamp freshness, circuit breaker status, price bounds

  • validation: Checks price > 0, timestamp < 1 hour old, within min/max bounds

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateTime, and lastPriceUpdateBlock when valid

  • events: Emits PriceUpdated when a valid price advances the baseline

  • errors: No errors thrown - returns fallback price if invalid

  • reentrancy: Not protected - external oracle reads only

  • access: Public - no access restrictions

  • oracle: Requires fresh Chainlink EUR/USD price feed data

function getEurUsdPrice() external returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals (e.g., 1.10e18 = 1.10 USD per EUR)
isValidbooltrue if the price is fresh and within acceptable bounds

getUsdcUsdPrice

Retrieves the USDC/USD price with validation

USDC is expected to maintain parity with USD. A large deviation indicates a systemic issue.

Notes:

  • security: Validates timestamp freshness, USDC tolerance bounds

  • validation: Checks price > 0, timestamp < 1 hour old, within USDC tolerance

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - returns $1.00 fallback if invalid

  • reentrancy: Not applicable - view function

  • access: Public - no access restrictions

  • oracle: Requires fresh Chainlink USDC/USD price feed data

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals (should be close to 1.0e18)
isValidbooltrue if USDC remains close to $1.00

updatePriceBounds

Updates price bounds for the circuit breaker

Allows oracle manager to adjust price thresholds based on market conditions

Notes:

  • security: Validates oracle manager role and price bounds constraints

  • validation: Validates _minPrice > 0, _maxPrice > _minPrice, _maxPrice < 10e18

  • state-changes: Updates minEurUsdPrice and maxEurUsdPrice

  • events: Emits PriceBoundsUpdated with new bounds

  • errors: Throws "Oracle: Min price must be positive" if _minPrice <= 0

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependencies for bounds update

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_minPriceuint256Minimum accepted EUR/USD price (18 decimals)
_maxPriceuint256Maximum accepted EUR/USD price (18 decimals)

updateUsdcTolerance

Updates the tolerance for USDC/USD

Allows oracle manager to adjust USDC price tolerance around $1.00

Notes:

  • security: Validates oracle manager role and tolerance constraints

  • validation: Validates newToleranceBps <= 1000 (max 10%)

  • state-changes: Updates usdcToleranceBps

  • events: No events emitted for tolerance update

  • errors: Throws "Oracle: Tolerance too high" if newToleranceBps > 1000

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependencies for tolerance update

function updateUsdcTolerance(uint256 newToleranceBps) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance in basis points (e.g., 200 = 2%)

updatePriceFeeds

Updates the Chainlink price feed addresses

Allows oracle manager to update price feed addresses for maintenance or upgrades

Notes:

  • security: Validates oracle manager role and feed address constraints

  • validation: Validates both feed addresses are not address(0)

  • state-changes: Updates eurUsdPriceFeed and usdcUsdPriceFeed interfaces

  • events: Emits PriceFeedsUpdated with new feed addresses

  • errors: Throws "Oracle: EUR/USD feed cannot be zero" if _eurUsdFeed is address(0)

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates Chainlink price feed interface addresses

function updatePriceFeeds(address _eurUsdFeed, address _usdcUsdFeed) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_eurUsdFeedaddressNew EUR/USD feed address
_usdcUsdFeedaddressNew USDC/USD feed address

proposeDevMode

Toggles dev mode to disable spread deviation checks

Propose a dev-mode change; enforces a 48-hour timelock before it can be applied.

DEV ONLY: When enabled, price deviation checks are skipped for testing

Stores the desired devModeEnabled value in pendingDevMode and sets devModePendingAt to block.timestamp + DEV_MODE_DELAY. No immediate effect on live price checks until applyDevMode is called after the delay.

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE

  • validation: No input validation required

  • state-changes: Updates devModeEnabled flag

  • events: Emits DevModeToggled event

  • errors: No errors thrown

  • reentrancy: Not protected - simple state change

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

  • security: Only callable by DEFAULT_ADMIN_ROLE; separates intent (propose) from effect (apply) to protect against rushed changes.

  • validation: Accepts both true and false; uses a fixed delay for all changes.

  • state-changes: Updates pendingDevMode and devModePendingAt.

  • events: Emits DevModeProposed(enabled, devModePendingAt).

  • errors: None – proposal is always recorded.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No direct oracle dependency; controls deviation checks in price paths.

function proposeDevMode(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable dev mode, false to disable

applyDevMode

Apply a previously proposed dev-mode change after the timelock has elapsed.

Reads pendingDevMode and sets devModeEnabled once block.timestamp is greater than or equal to devModePendingAt. Resets devModePendingAt back to 0 to clear the proposal.

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE; enforces a mandatory delay between proposal and activation of dev mode.

  • validation: Reverts if there is no pending proposal or the delay has not yet elapsed.

  • state-changes: Updates devModeEnabled and clears devModePendingAt.

  • events: Emits DevModeToggled(devModeEnabled, msg.sender).

  • errors: InvalidAmount if no pending proposal; NotActive if delay window not yet reached.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No direct oracle dependency; influences later deviation checks.

function applyDevMode() external onlyRole(DEFAULT_ADMIN_ROLE);

setSequencerUptimeFeed

Configure the L2 sequencer uptime feed for Base/Arbitrum deployments

Set feed to address(0) on L1 to skip the sequencer check. On Base mainnet use: 0xBCF85224fc0756B9Fa45aA7892530B47e10b6433

Notes:

  • security: Restricted to ORACLE_MANAGER_ROLE; sequencer checks gate oracle usage on L2s

  • validation: Caller must choose a grace period that is long enough to flush stale data

  • state-changes: Updates sequencerUptimeFeed and sequencerGracePeriod

  • events: Emits SequencerFeedUpdated with the new configuration

  • errors: No custom errors; relies on AccessControl for authorization checks

  • reentrancy: Not protected - no external calls beyond assigning storage and emitting an event

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Configures an auxiliary Chainlink feed used in getEurUsdPrice

function setSequencerUptimeFeed(address feed, uint256 gracePeriod) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
feedaddressChainlink sequencer uptime feed address (address(0) to disable)
gracePerioduint256Seconds to wait after sequencer restart before trusting prices again

Events

PriceUpdated

Emitted on each valid price update

OPTIMIZED: Indexed timestamp for efficient time-based filtering

event PriceUpdated(uint256 eurUsdPrice, uint256 usdcUsdPrice, uint256 indexed timestamp);

CircuitBreakerTriggered

Emitted when the circuit breaker is triggered

OPTIMIZED: Indexed reason for efficient filtering by trigger type

event CircuitBreakerTriggered(uint256 attemptedPrice, uint256 lastValidPrice, string indexed reason);

CircuitBreakerReset

Emitted when the circuit breaker is reset

event CircuitBreakerReset(address indexed admin);

PriceBoundsUpdated

Emitted when price bounds are modified

OPTIMIZED: Indexed bound type for efficient filtering

event PriceBoundsUpdated(string indexed boundType, uint256 newMinPrice, uint256 newMaxPrice);

PriceFeedsUpdated

Emitted when price feed addresses are updated

event PriceFeedsUpdated(address newEurUsdFeed, address newUsdcUsdFeed);

TreasuryUpdated

Emitted when treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

Parameters

NameTypeDescription
newTreasuryaddressNew treasury address

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

DevModeToggled

Emitted when dev mode is toggled

event DevModeToggled(bool enabled, address indexed caller);

Parameters

NameTypeDescription
enabledboolWhether dev mode is enabled or disabled
calleraddressAddress that triggered the toggle

DevModeProposed

Emitted when a dev-mode change is proposed

event DevModeProposed(bool pending, uint256 activatesAt);

Parameters

NameTypeDescription
pendingboolThe proposed dev-mode value
activatesAtuint256Timestamp at which the change can be applied

SequencerFeedUpdated

Emitted when the sequencer uptime feed is updated

event SequencerFeedUpdated(address indexed feed, uint256 gracePeriod);

IExecutionVault

Git Source

Vault reads required for execution previews.

Functions

paused

Whether vault settlement is paused for governance changes.

Read-only access to the vault's pause state.

Notes:

  • security: Used to gate pricing-limit changes.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: Propagates downstream read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: None.

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue while settlement is paused.

oracle

Read the vault reference oracle address.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function oracle() external view returns (address);

Returns

NameTypeDescription
<none>addressresult Value returned by the read interface.

usdc

Read the USDC token address.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressresult Value returned by the read interface.

mintFee

Read the protocol mint fee fraction.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function mintFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256result Value returned by the read interface.

redemptionFee

Read the protocol redemption fee fraction.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function redemptionFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256result Value returned by the read interface.

IExecutionRouter

Git Source

Router reads binding depth to the active hedge venue.

Functions

activeOracle

Read the active router slot.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function activeOracle() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8result Value returned by the read interface.

marketOracle

Read the router market oracle address.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function marketOracle() external view returns (address);

Returns

NameTypeDescription
<none>addressresult Value returned by the read interface.

ExecutionPricing

Git Source

Inherits: AccessControl, IExecutionPricing

Title: ExecutionPricing

Bounded, directional order-book pricing with persistent admission accounting.

Non-upgradeable module. Governance configures it on a paused vault after publishing depth. Reporter acknowledgments attest completed hedges; publishing alone never releases exposure.

Constants

SCALE

uint256 private constant SCALE = 1e30

BPS

uint256 private constant BPS = 10_000

MAX_LEVELS

Maximum number of executable price levels on each side.

uint256 public constant MAX_LEVELS = 20

WRITER_ROLE

Role authorized to publish observed Hyperliquid depth.

bytes32 public constant WRITER_ROLE = keccak256("WRITER_ROLE")

REPORTER_ROLE

Role authorized to acknowledge hedged exposure and margin capacity.

bytes32 public constant REPORTER_ROLE = keccak256("REPORTER_ROLE")

vault

Vault authorized to consume liquidity.

address public immutable override vault

venueOracle

Hyperliquid oracle required in the router's active market slot.

address public immutable venueOracle

reserveRecipient

Recipient of execution spread reserves.

address public immutable reserveRecipient

State Variables

maxAge

Maximum book and capacity observation age in seconds.

uint256 public maxAge

maxImpactBps

Maximum per-level deviation from the reference price in basis points.

uint256 public maxImpactBps

bufferBps

Venue fee and timing allowance incorporated into each execution rate.

uint256 public bufferBps

maxOutstanding

Governance ceiling on net directional unacknowledged EUR exposure.

uint256 public maxOutstanding

degradedHaircutBps

Haircut applied to reference-priced redemptions when execution data is unavailable.

uint256 public degradedHaircutBps = 25

riskLimitsUpdatedAt

Governance-update timestamp; subsequent reports must be observed after this time.

uint256 public riskLimitsUpdatedAt

asks

Level[] private asks

bids

Level[] private bids

observedAt

Original source observation time; never replaced by publication time.

uint256 public observedAt

sequence

Monotonic accepted snapshot revision.

uint256 public sequence

usedBuy

Buy-side quantity consumed from the current admission epoch.

uint256 public usedBuy

usedSell

Sell-side quantity consumed from the current admission epoch.

uint256 public usedSell

admittedBuy

Lifetime admitted quantities, used as replay-safe acknowledgment cursors.

uint256 public admittedBuy

admittedSell

uint256 public admittedSell

acknowledgedBuy

Lifetime hedge-acknowledged quantities.

uint256 public acknowledgedBuy

acknowledgedSell

uint256 public acknowledgedSell

acknowledgedAt

Time of the last complete hedge acknowledgment.

uint256 public acknowledgedAt

lastConsumptionBlock

Last block in which exposure was consumed.

uint256 public lastConsumptionBlock

marginCapacity

Reporter-certified additional margin capacity in EUR and its observation time.

uint256 public marginCapacity

capacityObservedAt

uint256 public capacityObservedAt

Functions

constructor

Deploy a vault-bound pricing module with explicit initial risk ceilings.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Explicit role separation; no default economic limits are inferred.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Deployment only; explicit role recipients are required.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

constructor(address[6] memory addresses, uint256[4] memory limits) ;

Parameters

NameTypeDescription
addressesaddress[6]Vault, Hyperliquid oracle, governance, depth writer, hedge reporter, reserve recipient.
limitsuint256[4]Maximum age (seconds), maximum impact (bps), rate buffer (bps), max outstanding EUR (18 decimals).

version

Implementation semantic version.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringresult Calculated result in the units described by this operation.

setDegradedHaircutBps

Sets the bounded haircut used by the redemption liveness fallback.

The setting applies only when a fresh coherent execution book cannot settle a redemption.

Notes:

  • security: Governance-only and only while the vault is paused.

  • validation: Rejects haircuts above the hard safety cap.

  • state-changes: Updates the fallback payout parameter.

  • events: Emits DegradedHaircutUpdated.

  • errors: InvalidCondition or InvalidParameter.

  • reentrancy: Only a read-only vault pause check.

  • access: DEFAULT_ADMIN_ROLE.

  • oracle: No oracle dependency.

function setDegradedHaircutBps(uint256 haircutBps) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
haircutBpsuint256Haircut in basis points, at most 1000 (10%).

updateRiskLimits

Update pricing limits on a paused vault after all admitted hedges are acknowledged.

Invalidates depth and capacity so subsequent quotes require newly observed reports.

Notes:

  • security: Governance only; cannot change the terms of pending admission.

  • validation: Requires paused settlement, zero outstanding admission and bounded limits.

  • state-changes: Updates limits, invalidates reports and clears consumed depth.

  • events: RiskLimitsUpdated.

  • errors: InvalidCondition for unsettled/unpaused vault; InvalidParameter for invalid limits.

  • reentrancy: Only a read-only call to the immutable vault.

  • access: DEFAULT_ADMIN_ROLE.

  • oracle: Fresh reports observed after the change are required before quoting.

function updateRiskLimits(uint256 age, uint256 impact, uint256 buffer, uint256 outstandingLimit)
    external
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
ageuint256Maximum source age in seconds, from 1 to 300.
impactuint256Maximum total per-level execution impact in bps, from 1 to 500.
bufferuint256Execution-rate buffer in bps, no greater than impact.
outstandingLimituint256Aggregate unacknowledged EUR ceiling in 18 decimals.

_validateRiskLimits

Validate pricing risk limits.

Applies the same bounds during deployment and governance updates.

Notes:

  • security: Caps source age and per-level impact.

  • validation: Age 1–300, impact 1–500, buffer at most impact, positive exposure limit.

  • state-changes: None.

  • events: None.

  • errors: InvalidParameter.

  • reentrancy: None.

  • access: Internal.

  • oracle: None.

function _validateRiskLimits(uint256 age, uint256 impact, uint256 buffer, uint256 outstandingLimit) private pure;

Parameters

NameTypeDescription
ageuint256Maximum source age in seconds.
impactuint256Maximum total execution impact in bps.
bufferuint256Execution-rate buffer in bps.
outstandingLimituint256Unacknowledged EUR limit in 18 decimals.

publish

Publish strictly ordered book levels with the original exchange timestamp.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: A newer observation cannot clear outstanding exposure or reset used depth prematurely.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: WRITER_ROLE only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function publish(uint256 sourceTime, Level[] calldata buy, Level[] calldata sell) external onlyRole(WRITER_ROLE);

Parameters

NameTypeDescription
sourceTimeuint256Source observation timestamp in seconds.
buyLevel[]Asks ordered by ascending price.
sellLevel[]Bids ordered by descending price.

acknowledge

Acknowledge all currently admitted exposure after canonical fills are reconciled.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Trusted reporter must reconcile fills and Base finality before calling; timestamps alone are not evidence.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: REPORTER_ROLE only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function acknowledge(uint256 buy, uint256 sell, uint256 capacity, uint256 sourceTime)
    external
    onlyRole(REPORTER_ROLE);

Parameters

NameTypeDescription
buyuint256Expected lifetime admitted buy quantity; rejects concurrent consumption.
selluint256Expected lifetime admitted sell quantity; rejects concurrent consumption.
capacityuint256Additional EUR capacity supported by currently available venue margin.
sourceTimeuint256Original account observation time in seconds.

reconcileAdmission

Reconcile admitted exposure during a governance-controlled pause.

Invalidates all reports; new depth and capacity must be observed after reconciliation.

Notes:

  • security: Governance must verify venue settlement before reconciling.

  • validation: Requires the immutable vault to be paused.

  • state-changes: Advances cursors and clears depth and capacity.

  • events: AdmissionReconciled.

  • errors: InvalidCondition if settlement is not paused.

  • reentrancy: Only a view call to the vault.

  • access: DEFAULT_ADMIN_ROLE.

  • oracle: Fresh reports required before further admission.

function reconcileAdmission() external onlyRole(DEFAULT_ADMIN_ROLE);

pendingExposure

Pending buy, sell, gross and absolute net exposure in QEURO units.

Net exposure is informational; opposite admissions do not release gross capacity.

Notes:

  • security: Read only.

  • validation: Cursors cannot exceed admission totals.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Public.

  • oracle: None.

function pendingExposure() public view returns (uint256 buy, uint256 sell, uint256 gross, uint256 net);

Returns

NameTypeDescription
buyuint256Unacknowledged buy quantity.
selluint256Unacknowledged sell quantity.
grossuint256Sum of pending quantities.
netuint256Absolute difference of pending quantities.

outstanding

Unacknowledged exposure across both directions, without speculative netting.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function outstanding() public view override returns (uint256);

Returns

NameTypeDescription
<none>uint256result Calculated result in the units described by this operation.

availableCapacity

Remaining executable EUR capacity on each side, including outstanding exposure limits.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function availableCapacity() external view returns (uint256 buy, uint256 sell);

Returns

NameTypeDescription
buyuint256Buy capacity in 18-decimal EUR units.
selluint256Sell capacity in 18-decimal EUR units.

previewMint

Exact-USDC-input mint preview, after the vault's protocol fee.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function previewMint(uint256 usdcInput) external view returns (Quote memory quote);

Parameters

NameTypeDescription
usdcInputuint256Value supplied to this operation.

Returns

NameTypeDescription
quoteQuoteCalculated result in the units described by this operation.

previewRedeem

Exact-QEURO-input normal-redemption preview, after the reference-valued protocol fee.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Public read access.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function previewRedeem(uint256 qeuroInput) external view returns (Quote memory quote);

Parameters

NameTypeDescription
qeuroInputuint256Value supplied to this operation.

Returns

NameTypeDescription
quoteQuoteCalculated result in the units described by this operation.

consumeMint

Consume buy liquidity and return minted quantity and reference backing.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Updates consumed liquidity counters.

  • events: LiquidityConsumed.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Configured vault only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function consumeMint(uint256 netUsdc, uint256 ref) external override returns (uint256 q, uint256 backing);

Parameters

NameTypeDescription
netUsdcuint256Net USDC input in 6 decimals.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
quint256Calculated result in the units described by this operation.
backinguint256Calculated result in the units described by this operation.

consumeRedeem

Consume sell liquidity and return the execution-valued payout.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Updates consumed liquidity counters.

  • events: LiquidityConsumed.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: Configured vault only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function consumeRedeem(uint256 q, uint256 ref) external override returns (uint256 payout);

Parameters

NameTypeDescription
quint256QEURO quantity in 18 decimals.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
payoutuint256Calculated result in the units described by this operation.

withdrawReserve

Transfer collected execution spreads to the immutable hedge reserve recipient.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Governance cannot redirect the reserve to an arbitrary recipient.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: Applies the effects described above.

  • events: Emits the events described above when applicable.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: Vault settlement is nonReentrant; publisher and reporter methods have no external state-changing callbacks.

  • access: DEFAULT_ADMIN_ROLE only.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function withdrawReserve(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
amountuint256USDC amount in 6 decimals.

_checkLevels

Validate nonzero strictly ordered executable book levels.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _checkLevels(Level[] calldata levels, bool buy) private pure;

Parameters

NameTypeDescription
levelsLevel[]Ordered executable price and quantity levels.
buyboolTrue for the buy side, false for the sell side.

_reference

Read a valid reference price for execution previews.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _reference() private view returns (uint256 ref);

Returns

NameTypeDescription
refuint256Calculated result in the units described by this operation.

_validate

Validate reference coherence, venue and observation freshness.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _validate(uint256 ref) private view;

Parameters

NameTypeDescription
refuint256Reference USD per EUR price in 18 decimals.

_bookCanExecuteRedeem

Checks whether published depth can price this redemption.

Missing capacity allows reference fallback; coherent fresh venue books must stay in bounds.

Notes:

  • security: Fresh divergent venue prices fail closed.

  • validation: Requires nonzero reference and quantity.

  • state-changes: None.

  • events: None.

  • errors: InvalidAmount or InvalidPrice.

  • reentrancy: Read-only router calls.

  • access: Private.

  • oracle: Uses the validated reference supplied by the vault.

function _bookCanExecuteRedeem(uint256 q, uint256 ref) private view returns (bool);

Parameters

NameTypeDescription
quint256Requested QEURO quantity.
refuint256Validated reference price.

Returns

NameTypeDescription
<none>boolWhether the normal book path can execute.

_degradedPayout

Applies the configured haircut to a reference redemption.

Rounds the payout down in USDC units.

Notes:

  • security: Cannot pay more than reference backing.

  • validation: Rejects zero payout.

  • state-changes: None.

  • events: None.

  • errors: InvalidAmount.

  • reentrancy: None.

  • access: Private.

  • oracle: Caller validates reference.

function _degradedPayout(uint256 q, uint256 ref) private view returns (uint256 payout);

Parameters

NameTypeDescription
quint256QEURO input.
refuint256Validated EUR/USD price.

Returns

NameTypeDescription
payoutuint256Payout before protocol fees.

_degradedHaircut

Returns the fallback haircut for the current observation state.

Fresh depth exhaustion uses at least the maximum book impact, preventing a better fallback quote.

Notes:

  • security: A fresh book cannot be bypassed for a better execution rate.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Private.

  • oracle: Uses publication age only.

function _degradedHaircut() private view returns (uint256);

Returns

NameTypeDescription
<none>uint256Haircut in basis points.

_rate

Calculate a conservative per-level execution rate.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _rate(uint256 price, bool buy, uint256 ref) private view returns (uint256);

Parameters

NameTypeDescription
priceuint256USD per EUR price in 18 decimals.
buyboolTrue for the buy side, false for the sell side.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
<none>uint256result Calculated result in the units described by this operation.

_capacity

Calculate remaining admitted capacity at the configured price limit.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _capacity(bool buy, uint256 ref) private view returns (uint256 capacity);

Parameters

NameTypeDescription
buyboolTrue for the buy side, false for the sell side.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
capacityuint256Calculated result in the units described by this operation.

_admissionRoom

Returns remaining net admission room for one execution side.

Opposite pending exposure may be offset before reaching the configured directional limit.

Notes:

  • security: Applies the governance and reporter capacity ceilings to every admission path.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Private helper.

  • oracle: Uses the last reported margin capacity, including during degraded execution.

function _admissionRoom(bool buy) private view returns (uint256 sideRoom);

Parameters

NameTypeDescription
buyboolTrue for buy-side admission, false for sell-side admission.

Returns

NameTypeDescription
sideRoomuint256Remaining quantity that can be admitted on the selected side.

_mint

Invert cumulative buy cost for an exact USDC input.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _mint(uint256 budget, uint256 ref) private view returns (uint256 q, uint256 backing);

Parameters

NameTypeDescription
budgetuint256Net USDC input in 6 decimals.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
quint256Calculated result in the units described by this operation.
backinguint256Calculated result in the units described by this operation.

_redeem

Calculate cumulative sell proceeds for a QEURO input.

Uses the documented units and preserves reference-price accounting.

Notes:

  • security: Uses explicit contract access boundaries and checked arithmetic.

  • validation: Validates the documented preconditions; view interface reads delegate to the target contract.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input, freshness, capacity or downstream contract errors as applicable.

  • reentrancy: No state changes.

  • access: Private helper.

  • oracle: Reference EUR/USD and observed venue depth where required; no oracle dependency for role and version reads.

function _redeem(uint256 q, uint256 ref) private view returns (uint256 payout);

Parameters

NameTypeDescription
quint256QEURO quantity in 18 decimals.
refuint256Reference USD per EUR price in 18 decimals.

Returns

NameTypeDescription
payoutuint256Calculated result in the units described by this operation.

Events

BookPublished

event BookPublished(uint256 indexed sequence, uint256 observedAt, uint256 usedBuy, uint256 usedSell);

LiquidityConsumed

event LiquidityConsumed(
    bool indexed mint,
    uint256 quantity,
    uint256 referencePrice,
    uint256 executionUsdc,
    uint256 admittedBuy,
    uint256 admittedSell
);

HedgeAcknowledged

event HedgeAcknowledged(uint256 admittedBuy, uint256 admittedSell, uint256 capacity, uint256 observedAt);

ReserveWithdrawn

event ReserveWithdrawn(address indexed recipient, uint256 amount);

RiskLimitsUpdated

event RiskLimitsUpdated(uint256 maxAge, uint256 maxImpactBps, uint256 bufferBps, uint256 maxOutstanding);

AdmissionReconciled

event AdmissionReconciled(uint256 admittedBuy, uint256 admittedSell);

DegradedHaircutUpdated

event DegradedHaircutUpdated(uint256 previousBps, uint256 newBps);

DegradedRedemption

event DegradedRedemption(uint256 quantity, uint256 referencePrice, uint256 payout, uint256 haircutBps);

Structs

Level

A price level with USD/EUR price and EUR quantity, both in 18 decimals.

struct Level {
    uint128 price;
    uint128 quantity;
}

Quote

Contract preview, including user output after protocol fees.

struct Quote {
    uint256 amountOut;
    uint256 executionRate;
    uint256 referenceRate;
    uint256 capacityQeuro;
    uint256 observedAt;
    uint256 sequence;
}

ISlippageMidSource

Git Source

Minimal read surface of SlippageStorage used by this adapter

Declared narrowly so the adapter depends only on the per-source mid read, letting both the real SlippageStorage and lightweight test doubles satisfy it without the full interface. The selector matches ISlippageStorage.getSlippageBySource(uint8).

Note: security-contact: team@quantillon.money

Functions

getSlippageBySource

Returns the latest slippage snapshot for a given source id

Narrow read surface so lightweight test doubles can satisfy the adapter without the full SlippageStorage interface.

Notes:

  • security: No security implications - view function

  • validation: No validation - interface definition

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Interface for SlippageStorage reads

function getSlippageBySource(uint8 sourceId)
    external
    view
    returns (ISlippageStorage.SlippageSnapshot memory snapshot);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_HYPERLIQUID = 1)

Returns

NameTypeDescription
snapshotISlippageStorage.SlippageSnapshotLatest snapshot; midPrice (18 decimals) and timestamp are used here

IReferencePriceSource

Git Source

Functions

peekEurUsdPrice

Reads an independent EUR/USD reference without cached-baseline substitution.

Returns validity, freshness timestamp, and scaled price.

Notes:

  • security: Read-only reference check.

  • validation: Implementations fail closed on stale or invalid rounds.

  • state-changes: None.

  • events: None.

  • errors: Implementations may revert on feed failure.

  • reentrancy: None.

  • access: Public view.

  • oracle: Chainlink EUR/USD.

function peekEurUsdPrice() external view returns (uint256 price, uint256 updatedAt, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals.
updatedAtuint256Feed timestamp.
isValidboolWhether the independent feed passed its checks.

HyperliquidEurUsdOracle

Git Source

Inherits: IHyperliquidOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: HyperliquidEurUsdOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

EUR/USD oracle for Quantillon that mirrors the Hyperliquid xyz:EUR perp mid used to execute the protocol hedge, so QEURO mint/redeem prices align with the hedge venue.

Design:

  • EUR/USD source: the Hyperliquid xyz:EUR mid published on-chain by the off-chain Slippage Monitor into SlippageStorage (getSlippageBySource(SOURCE_HYPERLIQUID).midPrice, 18 decimals). The snapshot timestamp is the on-chain write time, used for staleness.
  • USDC/USD source: delegated to the existing ChainlinkOracle (the hedge does not change USDC valuation), kept decoupled so a USDC feed issue cannot block EUR/USD reads.
  • Safety: configurable staleness, [min,max] price bounds, per-update deviation circuit breaker and a last-valid-price fallback — mirroring StorkOracle so the failure modes and the OracleRouter wiring are identical. Slots into the OracleRouter's Stork position: the router reads via IOracle and delegates updatePriceBounds / updateUsdcTolerance / resetCircuitBreaker / triggerCircuitBreaker, all of which are implemented here with matching selectors. No OracleRouter change is required.

Note: security-contact: team@quantillon.money

Constants

ORACLE_MANAGER_ROLE

Role to manage oracle configurations

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency actions

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for contract upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_PRICE_DEVIATION

Maximum allowed deviation from previous price (5% = 500 bps)

uint256 public constant MAX_PRICE_DEVIATION = 500

BASIS_POINTS

Basis for basis points calculations

uint256 public constant BASIS_POINTS = 10000

HARD_MAX_STALENESS

Hard upper bound for the configurable staleness window (1 hour)

uint256 public constant HARD_MAX_STALENESS = 3600

MID_DECIMALS

Published mid decimals (SlippageStorage stores midPrice in 18 decimals)

uint8 public constant MID_DECIMALS = 18

TIME_PROVIDER

TimeProvider contract for centralized, testable time

TimeProvider public immutable TIME_PROVIDER

State Variables

slippageStorage

SlippageStorage contract holding the published Hyperliquid mid

ISlippageMidSource public slippageStorage

usdcSource

USDC/USD source oracle (the existing ChainlinkOracle)

IOracle public usdcSource

sourceId

Slippage source id to read (SOURCE_HYPERLIQUID = 1)

uint8 public sourceId

treasury

Treasury address for ETH/token recovery

address public treasury

minEurUsdPrice

Minimum accepted EUR/USD price (lower circuit breaker, 18 decimals)

uint256 public minEurUsdPrice

maxEurUsdPrice

Maximum accepted EUR/USD price (upper circuit breaker, 18 decimals)

uint256 public maxEurUsdPrice

lastValidEurUsdPrice

Last valid EUR/USD price recorded (18 decimals) - used as fallback

uint256 public lastValidEurUsdPrice

lastPriceUpdateTime

Timestamp of the last valid price update

uint256 public lastPriceUpdateTime

lastPriceUpdateBlock

Block number of the last valid price update

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

Circuit breaker status (true = triggered, use last valid price)

bool public circuitBreakerTriggered

usdcToleranceBps

Reported USDC/USD tolerance in basis points (validation lives in usdcSource)

uint256 public usdcToleranceBps

maxPriceStaleness

Maximum accepted staleness of the published mid, in seconds

uint256 public maxPriceStaleness

maxReferenceDivergenceBps

Normal-hours divergence bound against the independent reference.

uint16 public maxReferenceDivergenceBps

maxReferenceDivergenceOffHoursBps

FX-closed-hours divergence bound against the independent reference.

uint16 public maxReferenceDivergenceOffHoursBps

maxReferenceAge

Maximum age of the independent reference in seconds.

uint32 public maxReferenceAge

Functions

version

Returns the semantic version of this implementation.

Pure getter read through the proxy; bump per semver on any change.

Notes:

  • security: No security implications - compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructor sets the TimeProvider and disables initializers for the proxy pattern

Stores the immutable TimeProvider and disables initializers on the implementation (UUPS pattern).

Notes:

  • security: Validates TimeProvider is non-zero

  • validation: Validates _TIME_PROVIDER != address(0)

  • state-changes: Sets TIME_PROVIDER immutable and disables initializers

  • events: No events emitted

  • errors: Reverts "Zero address" if _TIME_PROVIDER is zero

  • reentrancy: Not applicable - constructor

  • access: Public - anyone can deploy

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the TimeProvider contract

initialize

Initializes the adapter with its price sources and treasury

Grants admin/manager/emergency/upgrader roles to admin, sets default bounds, tolerance and staleness, then attempts a best-effort initial seed from SlippageStorage.

Notes:

  • security: Validates all addresses non-zero, grants roles to admin

  • validation: Validates admin/_slippageStorage/_usdcSource/_treasury != address(0)

  • state-changes: Initializes sources, roles, default bounds/staleness/tolerance, seeds price

  • events: Emits PriceUpdated if an initial mid is available

  • errors: Reverts if any address is zero

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during proxy deployment

  • oracle: Reads the initial mid from SlippageStorage if present

function initialize(
    address admin,
    address _slippageStorage,
    uint8 _sourceId,
    address _usdcSource,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_slippageStorageaddressSlippageStorage contract holding the published Hyperliquid mid
_sourceIduint8Slippage source id to read (SOURCE_HYPERLIQUID = 1)
_usdcSourceaddressOracle providing USDC/USD (the existing ChainlinkOracle)
_treasuryaddressTreasury address for ETH/token recovery

_divRound

Division with rounding to the nearest integer

Half-up integer division used for deviation-bps rounding.

Notes:

  • security: Validates denominator is positive

  • validation: Validates b > 0

  • state-changes: None - pure function

  • events: No events emitted

  • errors: Reverts if denominator is zero

  • reentrancy: Not protected - pure function

  • access: Internal

  • oracle: No oracle dependency

function _divRound(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256Numerator
buint256Denominator (must be > 0)

Returns

NameTypeDescription
<none>uint256Rounded result of a / b

_validateTimestamp

Validates the published mid timestamp against future-dating and staleness

SlippageStorage timestamps are on-chain write times, so they cannot be in the future except under clock skew; rejects zero and future observations. Normal snapshots use maxPriceStaleness. An explicitly emergency SignedReferenceSource uses its independent age policy, capped at 8100 seconds. This does not refresh timestamps or bypass price, independent-reference or circuit-breaker checks.

Notes:

  • security: Bounds acceptable data age for valuation reads

  • validation: Rejects zero, future, or stale timestamps

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - returns false on failure

  • reentrancy: Not protected - view function

  • access: Internal

  • oracle: Uses TimeProvider for current time

function _validateTimestamp(uint256 reportedTime) internal view returns (bool);

Parameters

NameTypeDescription
reportedTimeuint256The snapshot timestamp to validate

Returns

NameTypeDescription
<none>boolTrue if the timestamp is fresh and not future-dated

_readMid

Reads the latest Hyperliquid mid and its timestamp from SlippageStorage

try/catch read of the per-source snapshot; returns (0, 0) when SlippageStorage reverts.

Notes:

  • security: Single external view read of the trusted SlippageStorage

  • validation: No validation here - caller validates freshness/bounds

  • state-changes: None - view function

  • events: No events emitted

  • errors: Reverts only if SlippageStorage reverts (fail-safe for callers that bubble it)

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads SlippageStorage.getSlippageBySource(sourceId)

function _readMid() internal view returns (uint256 price, uint256 timestamp);

Returns

NameTypeDescription
priceuint256EUR/USD mid in 18 decimals (0 if unavailable)
timestampuint256On-chain write timestamp of the snapshot

_validateEurUsd

Validates a candidate EUR/USD price against freshness, bounds and deviation

Single validation path combining staleness/zero, min/max bounds, and deviation-vs-baseline checks.

Notes:

  • security: Enforces staleness, bounds and per-update deviation limits

  • validation: Returns isValid=false on stale, zero, out-of-bounds or over-deviation input

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - signals via (price, false)

  • reentrancy: Not protected - view function

  • access: Internal

  • oracle: Reads cached bounds/baseline only

function _validateEurUsd(uint256 price, uint256 timestamp) internal view returns (uint256 outPrice, bool isValid);

Parameters

NameTypeDescription
priceuint256Candidate price (18 decimals)
timestampuint256Snapshot timestamp

Returns

NameTypeDescription
outPriceuint256The candidate price echoed back (0 if it fails freshness)
isValidboolTrue if the price can advance the baseline

_referenceWithinBounds

Checks market price against the independent Chainlink reference.

Applies freshness and FX-hours divergence bounds; feed failures fail closed.

Notes:

  • security: Prevents an unbounded market publisher from setting protocol price.

  • validation: Rejects stale, invalid, or divergent references.

  • state-changes: None.

  • events: None.

  • errors: None; returns false on reference failure.

  • reentrancy: Read-only external probe.

  • access: Internal.

  • oracle: Chainlink EUR/USD.

function _referenceWithinBounds(uint256 price) internal view returns (bool);

Parameters

NameTypeDescription
priceuint256Market EUR/USD price in 18 decimals.

Returns

NameTypeDescription
<none>boolTrue when the reference is fresh and within the configured bound.

_readUsdcForEvent

Reads USDC/USD from the delegated source for event enrichment only

try/catch so a failing USDC source never blocks an EUR/USD commit.

Notes:

  • security: Isolates USDC-source failures from the EUR/USD path

  • validation: Falls back to 1e18 when the source reverts or returns invalid

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - falls back to 1e18

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads usdcSource.getUsdcUsdPrice()

function _readUsdcForEvent() internal view returns (uint256 usdcUsdPrice);

Returns

NameTypeDescription
usdcUsdPriceuint256USDC/USD price (18 decimals); $1.00 on any failure

_commitEurUsdPrice

Commits an accepted EUR/USD price as the new baseline

One TimeProvider read shared by the stored timestamp and the emitted event.

Notes:

  • security: Reached only after validation; advances the deviation baseline

  • validation: Assumes the caller validated the price

  • state-changes: Sets lastValidEurUsdPrice, lastPriceUpdateTime, lastPriceUpdateBlock

  • events: Emits PriceUpdated

  • errors: No errors thrown

  • reentrancy: Not protected - one external staticcall for event enrichment

  • access: Internal

  • oracle: Reads usdcSource for the emitted event only

function _commitEurUsdPrice(uint256 eurUsdPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Accepted EUR/USD price (18 decimals)

_seedInitialPrice

Best-effort initial/reset seed of the baseline from SlippageStorage

Never reverts and never trips the breaker: if no fresh, in-bounds mid is published yet, the baseline is left as-is and the first successful read seeds it.

Notes:

  • security: Avoids bricking init/reset when no data has been published yet

  • validation: Applies bounds (deviation is skipped while no baseline exists)

  • state-changes: May set lastValidEurUsdPrice/time/block via _commitEurUsdPrice

  • events: Emits PriceUpdated if a seed price is accepted

  • errors: No errors thrown

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads SlippageStorage

function _seedInitialPrice() internal;

getEurUsdPrice

Retrieves the current EUR/USD price with full validation

Reads the Hyperliquid mid from SlippageStorage; on circuit breaker, pause, staleness, out-of-bounds or over-deviation, returns the last valid price with isValid=false so the vault fails safe. A valid price advances the baseline.

Notes:

  • security: Validates freshness, bounds, deviation and breaker state

  • validation: Returns isValid=false for any invalid condition

  • state-changes: Updates baseline (lastValid*) when a valid price is accepted

  • events: Emits PriceUpdated when the baseline advances

  • errors: No errors thrown unless SlippageStorage itself reverts (fail-safe)

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage mid; reads usdcSource for the event only

function getEurUsdPrice() external override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if fresh and within bounds/deviation

getUsdcUsdPrice

Retrieves the USDC/USD price with validation, delegated to the USDC source

Delegates to the configured USDC source; falls back to ($1.00, false) when the source reverts.

Notes:

  • security: Delegates to the trusted USDC source; falls back to $1.00 on failure

  • validation: Validation performed by usdcSource

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - falls back to (1e18, false) on revert

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads usdcSource.getUsdcUsdPrice()

function getUsdcUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals (≈ 1e18)
isValidboolTrue if USDC remains within the source's tolerance

getOracleHealth

Returns overall oracle health signals

Aggregates mid freshness, USDC-source validity, circuit breaker and pause state for monitoring.

Notes:

  • security: Health view for monitoring and watchdog decisions

  • validation: Checks freshness, breaker and pause state

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - degraded sources report false

  • reentrancy: Not protected - external staticcalls only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage and usdcSource

function getOracleHealth() external view override returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthyboolTrue if both feeds are fresh, breaker is off and not paused
eurUsdFreshboolTrue if the Hyperliquid mid is fresh and positive
usdcUsdFreshboolTrue if the USDC source reports a valid price

getEurUsdDetails

Detailed information about the EUR/USD price

View-only variant of the read path; reuses _validateEurUsd for bounds/deviation.

Notes:

  • security: Detailed view for debugging and monitoring

  • validation: Checks freshness, bounds and deviation

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - returns fallback on source revert

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage

function getEurUsdDetails()
    external
    view
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be the fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Snapshot timestamp reported by SlippageStorage
isStaleboolTrue if the published mid is stale
withinBoundsboolTrue only when the published price itself passed all freshness, configured-bound, deviation, and reference checks

getOracleConfig

Current configuration and circuit breaker state

Returns the configured bounds, staleness window, USDC tolerance and breaker state in one call.

Notes:

  • security: Configuration view for monitoring

  • validation: No validation - read-only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: No oracle dependency

function getOracleConfig()
    external
    view
    override
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum accepted EUR/USD price
maxPriceuint256Maximum accepted EUR/USD price
maxStalenessuint256Maximum accepted staleness in seconds
usdcToleranceuint256Reported USDC tolerance in basis points
circuitBreakerActiveboolTrue if the circuit breaker is triggered

getPriceFeedAddresses

Addresses and decimals of the underlying sources

Reports the SlippageStorage and delegated USDC-source addresses currently wired.

Notes:

  • security: Returns source addresses for verification

  • validation: No validation - read-only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: No oracle dependency

function getPriceFeedAddresses()
    external
    view
    override
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD source address (SlippageStorage)
usdcUsdFeedAddressaddressUSDC/USD source address (ChainlinkOracle)
eurUsdDecimalsuint8EUR/USD decimals (18)
usdcUsdDecimalsuint8USDC/USD decimals (18)

checkPriceFeedConnectivity

Connectivity check for both sources

Best-effort staticcalls to both sources; never reverts.

Notes:

  • security: Connectivity view for monitoring

  • validation: No validation - connectivity test only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - degraded sources report false

  • reentrancy: Not protected - external staticcalls only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage and usdcSource

function checkPriceFeedConnectivity()
    external
    view
    override
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedboolTrue if SlippageStorage returns a fresh, positive mid
usdcUsdConnectedboolTrue if the USDC source returns a valid price
eurUsdLatestRounduint80Always 0 (not round-based)
usdcUsdLatestRounduint80Always 0 (not round-based)

updatePriceBounds

Updates EUR/USD min and max acceptable prices

The bounds gate _validateEurUsd; both must be nonzero with min below max.

Notes:

  • security: Validates min < max and a sane upper bound

  • validation: Validates _minPrice > 0, _maxPrice > _minPrice, _maxPrice <= 10e18

  • state-changes: Updates minEurUsdPrice and maxEurUsdPrice

  • events: Emits PriceBoundsUpdated

  • errors: Reverts on invalid bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_minPriceuint256Minimum accepted EUR/USD price (18 decimals)
_maxPriceuint256Maximum accepted EUR/USD price (18 decimals)

updateUsdcTolerance

Updates the reported USDC tolerance (validation lives in the USDC source)

Reported via getOracleConfig only — USDC validation itself is delegated to the USDC source.

Notes:

  • security: Validates tolerance within 10%

  • validation: Validates newToleranceBps <= 1000

  • state-changes: Updates usdcToleranceBps

  • events: No events emitted

  • errors: Reverts if tolerance is out of bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function updateUsdcTolerance(uint256 newToleranceBps) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance in basis points (e.g., 200 = 2%)

resetCircuitBreaker

Clears the circuit breaker and attempts to re-seed the baseline

Clears the breaker and attempts to re-seed the deviation baseline from the current mid.

Notes:

  • security: Re-enables live prices after manual intervention

  • validation: None

  • state-changes: Clears circuitBreakerTriggered and may re-seed the baseline

  • events: Emits CircuitBreakerReset (and PriceUpdated if re-seeded)

  • errors: No errors thrown

  • reentrancy: Not protected - external staticcall only

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Reads SlippageStorage to re-seed

function resetCircuitBreaker() external override onlyRole(EMERGENCY_ROLE);

forceReseedBaseline

Reseeds the deviation baseline from a fresh, independently bounded market mid.

Skips only the previous-baseline deviation check; freshness, absolute bounds, and the independent reference check remain mandatory.

Notes:

  • security: Restricted to EMERGENCY_ROLE and requires an enabled reference check.

  • validation: Reverts when the market mid or reference is stale, invalid, or divergent.

  • state-changes: Updates the baseline and clears the circuit breaker.

  • events: Emits PriceUpdated and CircuitBreakerReset.

  • errors: Reverts with InvalidPrice or InvalidOraclePrice when recovery data is unsafe.

  • reentrancy: Read-only source calls before one local state update.

  • access: EMERGENCY_ROLE.

  • oracle: Uses SlippageStorage and the independent Chainlink reference.

function forceReseedBaseline() external onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Manually triggers the circuit breaker (use last valid price)

Forces reads onto the last valid price until reset.

Notes:

  • security: Forces fallback pricing during incidents

  • validation: None

  • state-changes: Sets circuitBreakerTriggered to true

  • events: Emits CircuitBreakerTriggered

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependency

function triggerCircuitBreaker() external override onlyRole(EMERGENCY_ROLE);

setMaxPriceStaleness

Updates the maximum accepted staleness of the published mid

Gates _validateTimestamp; capped by MAX_STALENESS_CAP.

Notes:

  • security: Bounds the staleness window to a safe maximum

  • validation: Validates 0 < newMaxStaleness <= HARD_MAX_STALENESS

  • state-changes: Updates maxPriceStaleness

  • events: Emits MaxStalenessUpdated

  • errors: Reverts if out of bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function setMaxPriceStaleness(uint256 newMaxStaleness) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newMaxStalenessuint256New staleness window in seconds (1..HARD_MAX_STALENESS)

setReferenceCheck

Configures the independent EUR/USD reference check.

A zero normal-hours bound disables the cross-check.

Notes:

  • security: Restricted to ORACLE_MANAGER_ROLE and bounded to conservative limits.

  • validation: Zero disables the check; enabled values require a nonzero age.

  • state-changes: Updates reference divergence and age settings.

  • events: Emits PriceReferenceCheckUpdated.

  • errors: Reverts on invalid configuration.

  • reentrancy: No external calls.

  • access: ORACLE_MANAGER_ROLE.

  • oracle: No oracle reads.

function setReferenceCheck(uint16 normalBps, uint16 offHoursBps, uint32 referenceAge)
    external
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
normalBpsuint16Maximum normal-hours divergence in basis points.
offHoursBpsuint16Maximum FX-closed-hours divergence in basis points.
referenceAgeuint32Maximum accepted reference age in seconds.

updateSlippageSource

Updates the SlippageStorage source contract and source id

Points the adapter at a new SlippageStorage deployment and/or source id.

Notes:

  • security: Validates non-zero source address

  • validation: Validates _slippageStorage != address(0)

  • state-changes: Updates slippageStorage and sourceId

  • events: Emits SlippageSourceUpdated

  • errors: Reverts if source address is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates the SlippageStorage reference

function updateSlippageSource(address _slippageStorage, uint8 _sourceId)
    external
    override
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_slippageStorageaddressNew SlippageStorage contract address
_sourceIduint8New slippage source id (SOURCE_HYPERLIQUID = 1)

updateUsdcSource

Updates the USDC/USD source oracle

Swaps the delegated USDC/USD oracle.

Notes:

  • security: Validates non-zero source address

  • validation: Validates _usdcSource != address(0)

  • state-changes: Updates usdcSource

  • events: Emits UsdcSourceUpdated

  • errors: Reverts if source address is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates the USDC source reference

function updateUsdcSource(address _usdcSource) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_usdcSourceaddressNew USDC/USD source (ChainlinkOracle)

updateTreasury

Updates the treasury address

The treasury receives recovered tokens/ETH from the recovery functions.

Notes:

  • security: Validates non-zero treasury

  • validation: Validates _treasury != address(0)

  • state-changes: Updates treasury

  • events: Emits TreasuryUpdated

  • errors: Reverts if treasury is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function updateTreasury(address _treasury) external override onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

pause

Pauses all oracle reads

While paused, price reads return the last valid price with isValid=false.

Notes:

  • security: Emergency halt of price reads

  • validation: None

  • state-changes: Sets paused = true

  • events: Emits Paused

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Halts oracle price reads

function pause() external override onlyRole(EMERGENCY_ROLE);

unpause

Unpauses oracle reads

Re-enables live price reads.

Notes:

  • security: Resumes normal operation

  • validation: None

  • state-changes: Sets paused = false

  • events: Emits Unpaused

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Resumes oracle price reads

function unpause() external override onlyRole(EMERGENCY_ROLE);

recoverToken

Recovers ERC20 tokens accidentally sent to the contract, to treasury only

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Sends recovered tokens to treasury only

  • validation: Validated by the recovery library

  • state-changes: Transfers token balance to treasury

  • events: Emits TokenRecovered via library

  • errors: Reverts if token is zero or transfer fails

  • reentrancy: Protected by library

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverToken(address token, uint256 amount) external override onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to transfer

recoverETH

Recovers ETH accidentally sent to the contract, to treasury only

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Sends recovered ETH to treasury only

  • validation: Validates treasury is set and balance is non-zero

  • state-changes: Transfers ETH balance to treasury

  • events: Emits ETHRecovered

  • errors: Reverts if treasury is zero or there is no ETH

  • reentrancy: Uses sendValue to a trusted treasury

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverETH() external override onlyRole(DEFAULT_ADMIN_ROLE);

_authorizeUpgrade

Authorizes contract upgrades

Notes:

  • security: Restricted to UPGRADER_ROLE

  • validation: None beyond role check

  • state-changes: None directly

  • events: No events emitted

  • errors: Reverts if caller lacks UPGRADER_ROLE

  • reentrancy: Not protected - no external calls

  • access: Restricted to UPGRADER_ROLE

  • oracle: No oracle dependency

function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

Events

PriceUpdated

Emitted on each valid price update

event PriceUpdated(uint256 eurUsdPrice, uint256 usdcUsdPrice, uint256 indexed timestamp);

CircuitBreakerTriggered

Emitted when the circuit breaker is triggered

event CircuitBreakerTriggered(uint256 attemptedPrice, uint256 lastValidPrice, string indexed reason);

CircuitBreakerReset

Emitted when the circuit breaker is reset

event CircuitBreakerReset(address indexed admin);

PriceBoundsUpdated

Emitted when price bounds are modified

event PriceBoundsUpdated(string indexed boundType, uint256 newMinPrice, uint256 newMaxPrice);

SlippageSourceUpdated

Emitted when the slippage source contract or source id is updated

event SlippageSourceUpdated(address indexed newSlippageStorage, uint8 newSourceId);

UsdcSourceUpdated

Emitted when the USDC/USD source oracle is updated

event UsdcSourceUpdated(address indexed newUsdcSource);

MaxStalenessUpdated

Emitted when the maximum staleness window is updated

event MaxStalenessUpdated(uint256 oldStaleness, uint256 newStaleness);

PriceReferenceCheckUpdated

Emitted when independent reference validation is configured

event PriceReferenceCheckUpdated(uint16 normalBps, uint16 offHoursBps, uint32 referenceAge);

TreasuryUpdated

Emitted when the treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

ISlippageMidSource

Git Source

Minimal read surface of SlippageStorage used by this adapter

Declared narrowly so the adapter depends only on the per-source mid read, letting both the real SlippageStorage and lightweight test doubles satisfy it without the full interface. The selector matches ISlippageStorage.getSlippageBySource(uint8).

Note: security-contact: team@quantillon.money

Functions

getSlippageBySource

Returns the latest slippage snapshot for a given source id

Narrow read surface so lightweight test doubles can satisfy the adapter without the full SlippageStorage interface.

Notes:

  • security: No security implications - view function

  • validation: No validation - interface definition

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Interface for SlippageStorage reads

function getSlippageBySource(uint8 sourceId)
    external
    view
    returns (ISlippageStorage.SlippageSnapshot memory snapshot);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_LIGHTER = 0)

Returns

NameTypeDescription
snapshotISlippageStorage.SlippageSnapshotLatest snapshot; midPrice (18 decimals) and timestamp are used here

LighterEurUsdOracle

Git Source

Inherits: IHyperliquidOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: LighterEurUsdOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

EUR/USD oracle for Quantillon that mirrors the Lighter EURUSD (market_id 96) mid used to execute the protocol hedge, so QEURO mint/redeem prices align with the hedge venue.

Design:

  • EUR/USD source: the Lighter EURUSD mid published on-chain by the off-chain Slippage Monitor into SlippageStorage (getSlippageBySource(SOURCE_LIGHTER).midPrice, 18 decimals). The snapshot timestamp is the on-chain write time, used for staleness.
  • USDC/USD source: delegated to the existing ChainlinkOracle (the hedge does not change USDC valuation), kept decoupled so a USDC feed issue cannot block EUR/USD reads.
  • Safety: configurable staleness, [min,max] price bounds, per-update deviation circuit breaker and a last-valid-price fallback — mirroring StorkOracle so the failure modes and the OracleRouter wiring are identical. Slots into the OracleRouter's Stork position: the router reads via IOracle and delegates updatePriceBounds / updateUsdcTolerance / resetCircuitBreaker / triggerCircuitBreaker, all of which are implemented here with matching selectors. No OracleRouter change is required.

Note: security-contact: team@quantillon.money

Constants

ORACLE_MANAGER_ROLE

Role to manage oracle configurations

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency actions

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for contract upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_PRICE_DEVIATION

Maximum allowed deviation from previous price (5% = 500 bps)

uint256 public constant MAX_PRICE_DEVIATION = 500

BASIS_POINTS

Basis for basis points calculations

uint256 public constant BASIS_POINTS = 10000

HARD_MAX_STALENESS

Hard upper bound for the configurable staleness window (1 hour)

uint256 public constant HARD_MAX_STALENESS = 3600

MID_DECIMALS

Published mid decimals (SlippageStorage stores midPrice in 18 decimals)

uint8 public constant MID_DECIMALS = 18

TIME_PROVIDER

TimeProvider contract for centralized, testable time

TimeProvider public immutable TIME_PROVIDER

State Variables

slippageStorage

SlippageStorage contract holding the published Lighter mid

ISlippageMidSource public slippageStorage

usdcSource

USDC/USD source oracle (the existing ChainlinkOracle)

IOracle public usdcSource

sourceId

Slippage source id to read (SOURCE_LIGHTER = 0)

uint8 public sourceId

treasury

Treasury address for ETH/token recovery

address public treasury

minEurUsdPrice

Minimum accepted EUR/USD price (lower circuit breaker, 18 decimals)

uint256 public minEurUsdPrice

maxEurUsdPrice

Maximum accepted EUR/USD price (upper circuit breaker, 18 decimals)

uint256 public maxEurUsdPrice

lastValidEurUsdPrice

Last valid EUR/USD price recorded (18 decimals) - used as fallback

uint256 public lastValidEurUsdPrice

lastPriceUpdateTime

Timestamp of the last valid price update

uint256 public lastPriceUpdateTime

lastPriceUpdateBlock

Block number of the last valid price update

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

Circuit breaker status (true = triggered, use last valid price)

bool public circuitBreakerTriggered

usdcToleranceBps

Reported USDC/USD tolerance in basis points (validation lives in usdcSource)

uint256 public usdcToleranceBps

maxPriceStaleness

Maximum accepted staleness of the published mid, in seconds

uint256 public maxPriceStaleness

Functions

version

Returns the semantic version of this implementation.

Pure getter read through the proxy; bump per semver on any change.

Notes:

  • security: No security implications - compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructor sets the TimeProvider and disables initializers for the proxy pattern

Stores the immutable TimeProvider and disables initializers on the implementation (UUPS pattern).

Notes:

  • security: Validates TimeProvider is non-zero

  • validation: Validates _TIME_PROVIDER != address(0)

  • state-changes: Sets TIME_PROVIDER immutable and disables initializers

  • events: No events emitted

  • errors: Reverts "Zero address" if _TIME_PROVIDER is zero

  • reentrancy: Not applicable - constructor

  • access: Public - anyone can deploy

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the TimeProvider contract

initialize

Initializes the adapter with its price sources and treasury

Grants admin/manager/emergency/upgrader roles to admin and sets default bounds, tolerance and staleness. Does not auto-seed the EUR/USD baseline from SlippageStorage: the first published mid has no deviation check, so a trusted actor must call setBaselineEurUsdPrice after initialize (or after an upgrade that leaves the baseline unset). Until then, getEurUsdPrice returns (0, false).

Notes:

  • security: Validates all addresses non-zero, grants roles to admin

  • validation: Validates admin/_slippageStorage/_usdcSource/_treasury != address(0)

  • state-changes: Initializes sources, roles, default bounds/staleness/tolerance

  • events: No events emitted

  • errors: Reverts if any address is zero

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during proxy deployment

  • oracle: No oracle read at initialize; baseline is set via setBaselineEurUsdPrice

function initialize(
    address admin,
    address _slippageStorage,
    uint8 _sourceId,
    address _usdcSource,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_slippageStorageaddressSlippageStorage contract holding the published Lighter mid
_sourceIduint8Slippage source id to read (SOURCE_LIGHTER = 0)
_usdcSourceaddressOracle providing USDC/USD (the existing ChainlinkOracle)
_treasuryaddressTreasury address for ETH/token recovery

_divRound

Division with rounding to the nearest integer

Half-up integer division used for deviation-bps rounding.

Notes:

  • security: Validates denominator is positive

  • validation: Validates b > 0

  • state-changes: None - pure function

  • events: No events emitted

  • errors: Reverts if denominator is zero

  • reentrancy: Not protected - pure function

  • access: Internal

  • oracle: No oracle dependency

function _divRound(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256Numerator
buint256Denominator (must be > 0)

Returns

NameTypeDescription
<none>uint256Rounded result of a / b

_validateTimestamp

Validates the published mid timestamp against future-dating and staleness

SlippageStorage timestamps are on-chain write times, so they cannot be in the future except under clock skew; rejects zero (never published) and anything older than maxPriceStaleness.

Notes:

  • security: Bounds acceptable data age for valuation reads

  • validation: Rejects zero, future, or stale timestamps

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - returns false on failure

  • reentrancy: Not protected - view function

  • access: Internal

  • oracle: Uses TimeProvider for current time

function _validateTimestamp(uint256 reportedTime) internal view returns (bool);

Parameters

NameTypeDescription
reportedTimeuint256The snapshot timestamp to validate

Returns

NameTypeDescription
<none>boolTrue if the timestamp is fresh and not future-dated

_readMid

Reads the latest Lighter mid and its timestamp from SlippageStorage

try/catch read of the per-source snapshot; returns (0, 0) when SlippageStorage reverts, so the read path fails safe (falls back to the last valid price) instead of bubbling the revert. Mirrors the try/catch used by getOracleHealth/getEurUsdDetails on the same call.

Notes:

  • security: Single external view read of the trusted SlippageStorage

  • validation: No validation here - caller validates freshness/bounds

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - a reverting source read returns (0, 0)

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads SlippageStorage.getSlippageBySource(sourceId)

function _readMid() internal view returns (uint256 price, uint256 timestamp);

Returns

NameTypeDescription
priceuint256EUR/USD mid in 18 decimals (0 if unavailable)
timestampuint256On-chain write timestamp of the snapshot (0 if unavailable)

_validateEurUsd

Validates a candidate EUR/USD price against freshness, bounds and deviation

Single validation path combining staleness/zero, min/max bounds, and deviation-vs-baseline checks. An unset baseline (lastValidEurUsdPrice == 0) is never valid here: the first price is governance-only via setBaselineEurUsdPrice.

Notes:

  • security: Enforces staleness, bounds and per-update deviation limits

  • validation: Returns isValid=false on stale, zero, unseeded, out-of-bounds or over-deviation input

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - signals via (price, false)

  • reentrancy: Not protected - view function

  • access: Internal

  • oracle: Reads cached bounds/baseline only

function _validateEurUsd(uint256 price, uint256 timestamp) internal view returns (uint256 outPrice, bool isValid);

Parameters

NameTypeDescription
priceuint256Candidate price (18 decimals)
timestampuint256Snapshot timestamp

Returns

NameTypeDescription
outPriceuint256The candidate price echoed back (0 if it fails freshness)
isValidboolTrue if the price can advance the baseline

_readUsdcForEvent

Reads USDC/USD from the delegated source for event enrichment only

try/catch so a failing USDC source never blocks an EUR/USD commit. Returns 0 (not a fabricated $1.00) when the source reverts or reports an invalid price, so the emitted PriceUpdated event signals "USDC unavailable" rather than a misleadingly healthy peg.

Notes:

  • security: Isolates USDC-source failures from the EUR/USD path

  • validation: Returns 0 when the source reverts or returns invalid

  • state-changes: None - view function

  • events: No events emitted

  • errors: No errors thrown - returns 0 on failure

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads usdcSource.getUsdcUsdPrice()

function _readUsdcForEvent() internal view returns (uint256 usdcUsdPrice);

Returns

NameTypeDescription
usdcUsdPriceuint256USDC/USD price (18 decimals); 0 when unavailable/invalid

_commitEurUsdPrice

Commits an accepted EUR/USD price as the new baseline

One TimeProvider read shared by the stored timestamp and the emitted event.

Notes:

  • security: Reached only after validation; advances the deviation baseline

  • validation: Assumes the caller validated the price

  • state-changes: Sets lastValidEurUsdPrice, lastPriceUpdateTime, lastPriceUpdateBlock

  • events: Emits PriceUpdated

  • errors: No errors thrown

  • reentrancy: Not protected - one external staticcall for event enrichment

  • access: Internal

  • oracle: Reads usdcSource for the emitted event only

function _commitEurUsdPrice(uint256 eurUsdPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Accepted EUR/USD price (18 decimals)

_seedInitialPrice

Best-effort re-seed of an already-set baseline from SlippageStorage

Used by resetCircuitBreaker. Never reverts and never trips the breaker. Skips when the baseline is unset: the first price has no deviation check, so only setBaselineEurUsdPrice may establish it.

Notes:

  • security: Does not adopt a first mid from SlippageStorage

  • validation: Applies bounds and deviation against the existing baseline

  • state-changes: May set lastValidEurUsdPrice/time/block via _commitEurUsdPrice

  • events: Emits PriceUpdated if a seed price is accepted

  • errors: No errors thrown

  • reentrancy: Not protected - external staticcall only

  • access: Internal

  • oracle: Reads SlippageStorage

function _seedInitialPrice() internal;

_serveFallback

Serves the last valid EUR/USD price as an invalid fallback.

Used by getEurUsdPrice on breaker, pause, unseeded baseline, and rejected live mids. Does not update lastPriceUpdateTime/Block (that would make a stale price look fresh).

Notes:

  • security: Fail-safe return used by the vault's mint/redeem gate

  • validation: None

  • state-changes: None

  • events: Emits EurUsdFallbackServed

  • errors: No errors thrown

  • reentrancy: Not applicable

  • access: Internal

  • oracle: No oracle read

function _serveFallback() internal returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256Last valid EUR/USD price (0 if the baseline is unset)
isValidboolAlways false

getEurUsdPrice

Retrieves the current EUR/USD price with full validation

Reads the Lighter mid from SlippageStorage. On circuit breaker, pause, unseeded baseline, staleness, out-of-bounds, over-deviation, or a reverting source read, returns the last valid price with isValid=false so the vault fails safe. A valid price advances the baseline only when one is already set (the first baseline is governance-only).

Notes:

  • security: Validates freshness, bounds, deviation and breaker state

  • validation: Returns isValid=false for any invalid condition

  • state-changes: Updates baseline (lastValid*) when a valid price is accepted

  • events: Emits PriceUpdated when the baseline advances; EurUsdFallbackServed otherwise

  • errors: No errors thrown - a reverting source read falls back to the last valid price

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage mid; reads usdcSource for the event only

function getEurUsdPrice() external override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if fresh and within bounds/deviation

getUsdcUsdPrice

Retrieves the USDC/USD price with validation, delegated to the USDC source

Delegates to the configured USDC source; falls back to ($1.00, false) when the source reverts.

Notes:

  • security: Delegates to the trusted USDC source; falls back to $1.00 on failure

  • validation: Validation performed by usdcSource

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - falls back to (1e18, false) on revert

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads usdcSource.getUsdcUsdPrice()

function getUsdcUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals (≈ 1e18)
isValidboolTrue if USDC remains within the source's tolerance

getOracleHealth

Returns overall oracle health signals

Aggregates mid freshness, USDC-source validity, circuit breaker and pause state for monitoring.

Notes:

  • security: Health view for monitoring and watchdog decisions

  • validation: Checks freshness, breaker and pause state

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - degraded sources report false

  • reentrancy: Not protected - external staticcalls only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage and usdcSource

function getOracleHealth() external view override returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthyboolTrue if both feeds are fresh, breaker is off and not paused
eurUsdFreshboolTrue if the Lighter mid is fresh and positive
usdcUsdFreshboolTrue if the USDC source reports a valid price

getEurUsdDetails

Detailed information about the EUR/USD price

View-only variant of the read path; reuses _validateEurUsd for bounds/deviation.

Notes:

  • security: Detailed view for debugging and monitoring

  • validation: Checks freshness, bounds and deviation

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - returns fallback on source revert

  • reentrancy: Not protected - external staticcall only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage

function getEurUsdDetails()
    external
    view
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be the fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Snapshot timestamp reported by SlippageStorage
isStaleboolTrue if the published mid is stale
withinBoundsboolTrue if currentPrice is within configured bounds

getOracleConfig

Current configuration and circuit breaker state

Returns the configured bounds, staleness window, USDC tolerance and breaker state in one call.

Notes:

  • security: Configuration view for monitoring

  • validation: No validation - read-only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: No oracle dependency

function getOracleConfig()
    external
    view
    override
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum accepted EUR/USD price
maxPriceuint256Maximum accepted EUR/USD price
maxStalenessuint256Maximum accepted staleness in seconds
usdcToleranceuint256Reported USDC tolerance in basis points
circuitBreakerActiveboolTrue if the circuit breaker is triggered

getPriceFeedAddresses

Addresses and decimals of the underlying sources

Reports the SlippageStorage and delegated USDC-source addresses currently wired.

Notes:

  • security: Returns source addresses for verification

  • validation: No validation - read-only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: No oracle dependency

function getPriceFeedAddresses()
    external
    view
    override
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD source address (SlippageStorage)
usdcUsdFeedAddressaddressUSDC/USD source address (ChainlinkOracle)
eurUsdDecimalsuint8EUR/USD decimals (18)
usdcUsdDecimalsuint8USDC/USD decimals (18)

checkPriceFeedConnectivity

Connectivity check for both sources

Best-effort staticcalls to both sources; never reverts.

Notes:

  • security: Connectivity view for monitoring

  • validation: No validation - connectivity test only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - degraded sources report false

  • reentrancy: Not protected - external staticcalls only

  • access: Public - no access restrictions

  • oracle: Reads SlippageStorage and usdcSource

function checkPriceFeedConnectivity()
    external
    view
    override
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedboolTrue if SlippageStorage returns a fresh, positive mid
usdcUsdConnectedboolTrue if the USDC source returns a valid price
eurUsdLatestRounduint80Always 0 (not round-based)
usdcUsdLatestRounduint80Always 0 (not round-based)

updatePriceBounds

Updates EUR/USD min and max acceptable prices

The bounds gate _validateEurUsd; both must be nonzero with min below max. New bounds must also keep the current baseline (lastValidEurUsdPrice, when set) inside [min,max], so a bounds change cannot strand the read path on a now-out-of-bounds fallback. To re-bound away from the current baseline, move it first via setBaselineEurUsdPrice.

Notes:

  • security: Validates min < max and a sane upper bound

  • validation: Validates _minPrice > 0, _maxPrice > _minPrice, _maxPrice <= 10e18

  • state-changes: Updates minEurUsdPrice and maxEurUsdPrice

  • events: Emits PriceBoundsUpdated

  • errors: Reverts on invalid bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_minPriceuint256Minimum accepted EUR/USD price (18 decimals)
_maxPriceuint256Maximum accepted EUR/USD price (18 decimals)

setBaselineEurUsdPrice

Sets the EUR/USD deviation baseline explicitly (trusted seed / recovery).

The only way to establish the first baseline (initialize does not auto-seed, and getEurUsdPrice will not adopt a mid while lastValidEurUsdPrice is 0). Also used to recover a deviation-locked baseline: once set, a mid more than MAX_PRICE_DEVIATION away is rejected, and even resetCircuitBreaker cannot move it. Bounds-checked; deviation check is bypassed because this is a trusted governance write.

Notes:

  • security: Governance-only; bounds-checked; emits an explicit audit event.

  • validation: Reverts unless minEurUsdPrice <= price <= maxEurUsdPrice.

  • state-changes: Sets lastValidEurUsdPrice/time/block via _commitEurUsdPrice.

  • events: Emits BaselinePriceSet and PriceUpdated.

  • errors: Reverts if price is outside the configured bounds.

  • reentrancy: Not protected - one external staticcall for event enrichment.

  • access: Restricted to ORACLE_MANAGER_ROLE.

  • oracle: Reads usdcSource for the emitted event only.

function setBaselineEurUsdPrice(uint256 price) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
priceuint256New baseline EUR/USD price (18 decimals); must be within the configured bounds.

updateUsdcTolerance

Updates the reported USDC tolerance (validation lives in the USDC source)

Reported via getOracleConfig only; USDC validation itself is delegated to the USDC source. This value is advisory (observability), so the setter emits an event for auditability.

Notes:

  • security: Validates tolerance within 10%

  • validation: Validates newToleranceBps <= 1000

  • state-changes: Updates usdcToleranceBps

  • events: Emits UsdcToleranceUpdated

  • errors: Reverts if tolerance is out of bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function updateUsdcTolerance(uint256 newToleranceBps) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance in basis points (e.g., 200 = 2%)

resetCircuitBreaker

Clears the circuit breaker and attempts to re-seed the baseline

Clears the breaker and attempts to re-seed the deviation baseline from the current mid.

Notes:

  • security: Re-enables live prices after manual intervention

  • validation: None

  • state-changes: Clears circuitBreakerTriggered and may re-seed the baseline

  • events: Emits CircuitBreakerReset (and PriceUpdated if re-seeded)

  • errors: No errors thrown

  • reentrancy: Not protected - external staticcall only

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Reads SlippageStorage to re-seed

function resetCircuitBreaker() external override onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Manually triggers the circuit breaker (use last valid price)

Forces reads onto the last valid price until reset.

Notes:

  • security: Forces fallback pricing during incidents

  • validation: None

  • state-changes: Sets circuitBreakerTriggered to true

  • events: Emits CircuitBreakerTriggered

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependency

function triggerCircuitBreaker() external override onlyRole(EMERGENCY_ROLE);

setMaxPriceStaleness

Updates the maximum accepted staleness of the published mid

Gates _validateTimestamp; capped by MAX_STALENESS_CAP.

Notes:

  • security: Bounds the staleness window to a safe maximum

  • validation: Validates 0 < newMaxStaleness <= HARD_MAX_STALENESS

  • state-changes: Updates maxPriceStaleness

  • events: Emits MaxStalenessUpdated

  • errors: Reverts if out of bounds

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency

function setMaxPriceStaleness(uint256 newMaxStaleness) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newMaxStalenessuint256New staleness window in seconds (1..HARD_MAX_STALENESS)

updateSlippageSource

Updates the SlippageStorage source contract and source id

Points the adapter at a new SlippageStorage deployment and/or source id.

Notes:

  • security: Validates non-zero source address

  • validation: Validates _slippageStorage != address(0)

  • state-changes: Updates slippageStorage and sourceId

  • events: Emits SlippageSourceUpdated

  • errors: Reverts if source address is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates the SlippageStorage reference

function updateSlippageSource(address _slippageStorage, uint8 _sourceId)
    external
    override
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_slippageStorageaddressNew SlippageStorage contract address
_sourceIduint8New slippage source id (SOURCE_LIGHTER = 0)

updateUsdcSource

Updates the USDC/USD source oracle

Swaps the delegated USDC/USD oracle.

Notes:

  • security: Validates non-zero source address

  • validation: Validates _usdcSource != address(0)

  • state-changes: Updates usdcSource

  • events: Emits UsdcSourceUpdated

  • errors: Reverts if source address is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates the USDC source reference

function updateUsdcSource(address _usdcSource) external override onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_usdcSourceaddressNew USDC/USD source (ChainlinkOracle)

updateTreasury

Updates the treasury address

The treasury receives recovered tokens/ETH from the recovery functions.

Notes:

  • security: Validates non-zero treasury

  • validation: Validates _treasury != address(0)

  • state-changes: Updates treasury

  • events: Emits TreasuryUpdated

  • errors: Reverts if treasury is zero

  • reentrancy: Not protected - no external calls

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function updateTreasury(address _treasury) external override onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

pause

Pauses all oracle reads

While paused, price reads return the last valid price with isValid=false.

Notes:

  • security: Emergency halt of price reads

  • validation: None

  • state-changes: Sets paused = true

  • events: Emits Paused

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Halts oracle price reads

function pause() external override onlyRole(EMERGENCY_ROLE);

unpause

Unpauses oracle reads

Re-enables live price reads.

Notes:

  • security: Resumes normal operation

  • validation: None

  • state-changes: Sets paused = false

  • events: Emits Unpaused

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Resumes oracle price reads

function unpause() external override onlyRole(EMERGENCY_ROLE);

recoverToken

Recovers ERC20 tokens accidentally sent to the contract, to treasury only

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Sends recovered tokens to treasury only

  • validation: Validated by the recovery library

  • state-changes: Transfers token balance to treasury

  • events: Emits TokenRecovered via library

  • errors: Reverts if token is zero or transfer fails

  • reentrancy: Protected by library

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverToken(address token, uint256 amount) external override onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to transfer

recoverETH

Recovers ETH accidentally sent to the contract, to treasury only

Routed through TreasuryRecoveryLibrary; funds always go to the treasury.

Notes:

  • security: Sends recovered ETH to treasury only

  • validation: Validates treasury is set and balance is non-zero

  • state-changes: Transfers ETH balance to treasury

  • events: Emits ETHRecovered

  • errors: Reverts if treasury is zero or there is no ETH

  • reentrancy: Uses sendValue to a trusted treasury

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverETH() external override onlyRole(DEFAULT_ADMIN_ROLE);

_authorizeUpgrade

Authorizes contract upgrades

Notes:

  • security: Restricted to UPGRADER_ROLE

  • validation: None beyond role check

  • state-changes: None directly

  • events: No events emitted

  • errors: Reverts if caller lacks UPGRADER_ROLE

  • reentrancy: Not protected - no external calls

  • access: Restricted to UPGRADER_ROLE

  • oracle: No oracle dependency

function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

Events

PriceUpdated

Emitted on each valid price update

event PriceUpdated(uint256 eurUsdPrice, uint256 usdcUsdPrice, uint256 indexed timestamp);

CircuitBreakerTriggered

Emitted when the circuit breaker is triggered

event CircuitBreakerTriggered(uint256 attemptedPrice, uint256 lastValidPrice, string indexed reason);

CircuitBreakerReset

Emitted when the circuit breaker is reset

event CircuitBreakerReset(address indexed admin);

PriceBoundsUpdated

Emitted when price bounds are modified

event PriceBoundsUpdated(string indexed boundType, uint256 newMinPrice, uint256 newMaxPrice);

SlippageSourceUpdated

Emitted when the slippage source contract or source id is updated

event SlippageSourceUpdated(address indexed newSlippageStorage, uint8 newSourceId);

UsdcSourceUpdated

Emitted when the USDC/USD source oracle is updated

event UsdcSourceUpdated(address indexed newUsdcSource);

MaxStalenessUpdated

Emitted when the maximum staleness window is updated

event MaxStalenessUpdated(uint256 oldStaleness, uint256 newStaleness);

UsdcToleranceUpdated

Emitted when the reported USDC tolerance is updated

event UsdcToleranceUpdated(uint256 oldToleranceBps, uint256 newToleranceBps);

EurUsdFallbackServed

Emitted when a live read is rejected and the last valid price is served (isValid=false)

event EurUsdFallbackServed(uint256 lastValidEurUsdPrice);

BaselinePriceSet

Emitted when governance explicitly sets the EUR/USD baseline (trusted seed / recovery)

event BaselinePriceSet(uint256 oldPrice, uint256 newPrice);

TreasuryUpdated

Emitted when the treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

OracleRouter

Git Source

Inherits: IOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: OracleRouter

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Router contract that lets governance switch the protocol between two oracle slots

Key features:

  • Holds references to two oracle slots (enum OracleType { CHAINLINK, MARKET }); the MARKET slot can host any IOracle implementation (StorkOracle pre-2026-06-25, HyperliquidEurUsdOracle since)
  • Routes all IOracle calls to the currently active oracle
  • Admin can switch between oracles via switchOracle()
  • v1.1.0: slot 1 renamed STORK -> MARKET / storkOracle -> marketOracle; the pre-1.1.0 storkOracle() getter is kept as a deprecated ABI-compatible alias
  • Implements IOracle interface (generic, oracle-agnostic)
  • Protocol contracts use IOracle interface for oracle-agnostic integration

Note: security-contact: team@quantillon.money

Constants

ORACLE_MANAGER_ROLE

Role to manage oracle configurations

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency actions

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for contract upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

State Variables

chainlinkOracle

Chainlink oracle contract reference

IChainlinkOracle public chainlinkOracle

marketOracle

Market oracle contract reference (slot 1)

The swappable market-price oracle: StorkOracle pre-2026-06-25, currently HyperliquidEurUsdOracle. Named storkOracle before v1.1.0 (same slot/encoding).

IOracle public marketOracle

activeOracle

Currently active oracle type

OracleType public activeOracle

treasury

Treasury address for ETH recovery

address public treasury

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Locks the implementation so it cannot be initialized directly

Disables initializers on the implementation contract; only proxies may be initialized. Brings OracleRouter in line with the other core/oracle contracts, which all call _disableInitializers().

Notes:

  • security: Prevents implementation-contract initialization

  • validation: No input validation required - constructor

  • state-changes: Disables initializers on the implementation

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - constructor

  • access: No access restrictions

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initializes the router contract with both oracle addresses

Sets up all core dependencies, roles, and default oracle selection

Notes:

  • security: Validates all addresses are not zero, grants admin roles

  • validation: Validates all input addresses are not address(0)

  • state-changes: Initializes all state variables, sets default oracle

  • events: Emits OracleSwitched during initialization

  • errors: Throws validation errors if addresses are zero

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during deployment

  • oracle: Initializes references to the chainlink and market oracle contracts

function initialize(
    address admin,
    address _chainlinkOracle,
    address _marketOracle,
    address _treasury,
    OracleType _defaultOracle
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_chainlinkOracleaddressChainlinkOracle contract address
_marketOracleaddressMarket oracle contract address (slot 1)
_treasuryaddressTreasury address for ETH recovery
_defaultOracleOracleTypeDefault oracle to use (CHAINLINK or MARKET)

updateTreasury

Update treasury address

Only admin can update treasury address

Notes:

  • security: Restricted to DEFAULT_ADMIN_ROLE

  • validation: _treasury not zero

  • state-changes: treasury

  • events: TreasuryUpdated

  • errors: InvalidAddress if zero

  • reentrancy: No external calls

  • access: DEFAULT_ADMIN_ROLE

  • oracle: None

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

unpause

Removes pause and resumes oracle operations

Only emergency role can unpause the router

Notes:

  • security: Restricted to EMERGENCY_ROLE

  • validation: None

  • state-changes: Pausable state

  • events: Unpaused

  • errors: None

  • reentrancy: No external calls

  • access: EMERGENCY_ROLE

  • oracle: None

function unpause() external onlyRole(EMERGENCY_ROLE);

_getActiveOracle

Gets the currently active oracle contract

Returns chainlinkOracle or marketOracle based on activeOracle enum

Notes:

  • security: View only

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal

  • oracle: Returns oracle reference

function _getActiveOracle() internal view returns (IOracle);

Returns

NameTypeDescription
<none>IOracleThe active oracle contract implementing IOracle

getActiveOracle

Gets the currently active oracle type

Returns activeOracle enum value

Notes:

  • security: View only

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Anyone

  • oracle: None

function getActiveOracle() external view returns (OracleType);

Returns

NameTypeDescription
<none>OracleTypeThe active oracle type (CHAINLINK or MARKET)

getOracleAddresses

Gets the addresses of both oracle contracts

Returns chainlinkOracle and marketOracle addresses

Notes:

  • security: View only

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Anyone

  • oracle: None

function getOracleAddresses() external view returns (address chainlinkAddress, address marketAddress);

Returns

NameTypeDescription
chainlinkAddressaddressAddress of ChainlinkOracle contract
marketAddressaddressAddress of the market oracle contract (slot 1)

storkOracle

Deprecated alias for the slot-1 (market) oracle address

Before v1.1.0 the slot-1 state variable was named storkOracle; this function preserves the auto-generated getter's selector and return type for ABI compatibility. New integrations must use marketOracle() instead.

Notes:

  • security: View only

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Anyone

  • oracle: Returns the market oracle reference

function storkOracle() external view returns (IStorkOracle);

Returns

NameTypeDescription
<none>IStorkOracleThe slot-1 oracle, typed as IStorkOracle for ABI compatibility

_authorizeUpgrade

Authorizes router contract upgrades

function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

recoverToken

Recovers tokens accidentally sent to the contract to treasury only

Delegates to TreasuryRecoveryLibrary.recoverToken

Notes:

  • security: DEFAULT_ADMIN_ROLE; sends to treasury only

  • validation: Treasury and amount

  • state-changes: Token balance of treasury

  • events: Via TreasuryRecoveryLibrary

  • errors: Via library

  • reentrancy: External call to token and treasury

  • access: DEFAULT_ADMIN_ROLE

  • oracle: None

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressAddress of the token to recover
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

Delegates to TreasuryRecoveryLibrary.recoverETH; emits ETHRecovered

Notes:

  • security: DEFAULT_ADMIN_ROLE; sends to treasury only

  • validation: Treasury not zero

  • state-changes: ETH balance of treasury

  • events: ETHRecovered

  • errors: Via library

  • reentrancy: External call to treasury

  • access: DEFAULT_ADMIN_ROLE

  • oracle: None

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

pause

Pauses all oracle operations

Calls _pause(); only EMERGENCY_ROLE

Notes:

  • security: EMERGENCY_ROLE only

  • validation: None

  • state-changes: Pausable state

  • events: Paused

  • errors: None

  • reentrancy: No external calls

  • access: EMERGENCY_ROLE

  • oracle: None

function pause() external onlyRole(EMERGENCY_ROLE);

switchOracle

Switches the active oracle between the two slots

Validates newOracle != activeOracle and oracle address not zero; emits OracleSwitched

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: newOracle != activeOracle; oracle address not zero

  • state-changes: activeOracle

  • events: OracleSwitched

  • errors: Require message if same oracle

  • reentrancy: No external calls

  • access: ORACLE_MANAGER_ROLE

  • oracle: None

function switchOracle(OracleType newOracle) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newOracleOracleTypeThe new oracle type to activate (CHAINLINK or MARKET)

updateOracleAddresses

Updates the oracle contract addresses

Validates both addresses; updates chainlinkOracle and marketOracle; emits OracleAddressesUpdated

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: Both addresses not zero

  • state-changes: chainlinkOracle, marketOracle

  • events: OracleAddressesUpdated

  • errors: InvalidOracle if zero

  • reentrancy: No external calls

  • access: ORACLE_MANAGER_ROLE

  • oracle: None

function updateOracleAddresses(address _chainlinkOracle, address _marketOracle)
    external
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_chainlinkOracleaddressNew ChainlinkOracle address
_marketOracleaddressNew market oracle address (slot 1)

getEurUsdPrice

Retrieves the current EUR/USD price with full validation

Delegates to active oracle getEurUsdPrice()

Notes:

  • security: Delegates to trusted oracle

  • validation: Via oracle

  • state-changes: May update oracle state (e.g. last price)

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: Anyone

  • oracle: Delegates to active oracle

function getEurUsdPrice() external override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolTrue if the price is fresh and within acceptable bounds

getUsdcUsdPrice

Retrieves the USDC/USD price with validation

Delegates to active oracle getUsdcUsdPrice()

Notes:

  • security: View; delegates to oracle

  • validation: Via oracle

  • state-changes: None

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle (view)

  • access: Anyone

  • oracle: Delegates to active oracle

function getUsdcUsdPrice() external view override returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals
isValidboolTrue if USDC remains close to $1.00

getOracleHealth

Returns overall oracle health signals

Delegates to active oracle getOracleHealth()

Notes:

  • security: Delegates to oracle

  • validation: Via oracle

  • state-changes: May update oracle state

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: Anyone

  • oracle: Delegates to active oracle

function getOracleHealth() external override returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthyboolTrue if both feeds are fresh, circuit breaker is off, and not paused
eurUsdFreshboolTrue if EUR/USD feed is fresh
usdcUsdFreshboolTrue if USDC/USD feed is fresh

getEurUsdDetails

Detailed information about the EUR/USD price

Delegates to active oracle getEurUsdDetails()

Notes:

  • security: Delegates to oracle

  • validation: Via oracle

  • state-changes: No state changes - view function only

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: Anyone

  • oracle: Delegates to active oracle

function getEurUsdDetails()
    external
    view
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Timestamp reported by the underlying EUR/USD feed
isStaleboolTrue if the feed data is stale
withinBoundsboolTrue if within configured min/max bounds

getOracleConfig

Current configuration and circuit breaker state

Delegates to active oracle getOracleConfig()

Notes:

  • security: View; delegates to oracle

  • validation: Via oracle

  • state-changes: None

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle (view)

  • access: Anyone

  • oracle: Delegates to active oracle

function getOracleConfig()
    external
    view
    override
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum accepted EUR/USD price
maxPriceuint256Maximum accepted EUR/USD price
maxStalenessuint256Maximum allowed staleness in seconds
usdcToleranceuint256USDC tolerance in basis points
circuitBreakerActiveboolTrue if circuit breaker is triggered

getPriceFeedAddresses

Addresses and decimals of the underlying feeds

Delegates to active oracle getPriceFeedAddresses()

Notes:

  • security: View; delegates to oracle

  • validation: Via oracle

  • state-changes: None

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle (view)

  • access: Anyone

  • oracle: Delegates to active oracle

function getPriceFeedAddresses()
    external
    view
    override
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD feed address
usdcUsdFeedAddressaddressUSDC/USD feed address
eurUsdDecimalsuint8EUR/USD feed decimals
usdcUsdDecimalsuint8USDC/USD feed decimals

checkPriceFeedConnectivity

Connectivity check for both feeds

Delegates to active oracle checkPriceFeedConnectivity()

Notes:

  • security: View; delegates to oracle

  • validation: Via oracle

  • state-changes: None

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle (view)

  • access: Anyone

  • oracle: Delegates to active oracle

function checkPriceFeedConnectivity()
    external
    view
    override
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedboolTrue if EUR/USD feed responds
usdcUsdConnectedboolTrue if USDC/USD feed responds
eurUsdLatestRounduint80Latest round ID for EUR/USD
usdcUsdLatestRounduint80Latest round ID for USDC/USD

updatePriceBounds

Updates EUR/USD min and max acceptable prices

Delegates to active oracle updatePriceBounds

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: Via oracle

  • state-changes: Oracle state

  • events: Via oracle

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: ORACLE_MANAGER_ROLE

  • oracle: Delegates to active oracle

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_minPriceuint256New minimum price (18 decimals)
_maxPriceuint256New maximum price (18 decimals)

updateUsdcTolerance

Updates the allowed USDC deviation from $1.00 in basis points

Delegates to active oracle updateUsdcTolerance

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: Via oracle

  • state-changes: Oracle state

  • events: Via oracle

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: ORACLE_MANAGER_ROLE

  • oracle: Delegates to active oracle

function updateUsdcTolerance(uint256 newToleranceBps) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance (e.g., 200 = 2%)

updatePriceFeeds

Updates price feed addresses (Chainlink only)

Reverts when the MARKET slot is active - use oracle-specific methods instead

Notes:

  • security: Only Chainlink path; reverts for the MARKET slot

  • validation: Via ChainlinkOracle

  • state-changes: Oracle feed addresses

  • events: Via oracle

  • errors: Reverts for the MARKET slot

  • reentrancy: External call to ChainlinkOracle

  • access: ORACLE_MANAGER_ROLE

  • oracle: Delegates to ChainlinkOracle only

function updatePriceFeeds(address _eurUsdFeed, address _usdcUsdFeed) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_eurUsdFeedaddressNew EUR/USD feed address
_usdcUsdFeedaddressNew USDC/USD feed address

resetCircuitBreaker

Clears circuit breaker and attempts to resume live prices

Delegates to active oracle resetCircuitBreaker()

Notes:

  • security: Anyone can reset (oracle may restrict)

  • validation: Via oracle

  • state-changes: Oracle circuit breaker state

  • events: Via oracle

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: ORACLE_MANAGER_ROLE

  • oracle: Delegates to active oracle

function resetCircuitBreaker() external onlyRole(ORACLE_MANAGER_ROLE);

triggerCircuitBreaker

Manually triggers circuit breaker to use fallback prices

Delegates to active oracle triggerCircuitBreaker()

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: Via oracle

  • state-changes: Oracle circuit breaker state

  • events: Via oracle

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: ORACLE_MANAGER_ROLE

  • oracle: Delegates to active oracle

function triggerCircuitBreaker() external onlyRole(ORACLE_MANAGER_ROLE);

Events

OracleSwitched

Emitted when the active oracle is switched

OPTIMIZED: Indexed oracle type for efficient filtering

event OracleSwitched(OracleType indexed oldOracle, OracleType indexed newOracle, address indexed caller);

OracleAddressesUpdated

Emitted when oracle addresses are updated

event OracleAddressesUpdated(address newChainlinkOracle, address newMarketOracle);

TreasuryUpdated

Emitted when treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

Enums

OracleType

Enum for oracle type selection

Slot 1 was named STORK before v1.1.0; renamed to MARKET (the swappable market-price oracle slot). Enum values are unchanged (CHAINLINK=0, MARKET=1).

enum OracleType {
    CHAINLINK,
    MARKET
}

PublicationBatcher

Git Source

Inherits: IVersioned

Title: PublicationBatcher

Publishes market summaries and execution depth in one transaction.

Immutable, non-upgradeable forwarding contract. Existing target validation and events are preserved, including SlippageStorage's per-source skips. Governance must grant this contract WRITER_ROLE on both destinations.

Notes:

  • security: Only the fixed writer can call the two fixed publication selectors.

  • security-contact: team@quantillon.money

Constants

writer

Account authorized to submit combined publications.

address public immutable writer

priceStore

SlippageStorage destination for market summaries.

address public immutable priceStore

depthStore

ExecutionPricing destination for executable order books.

address public immutable depthStore

PRICE_SELECTOR

The sole allowed SlippageStorage entry point.

bytes4 private constant PRICE_SELECTOR =
    bytes4(keccak256("updateSlippageBatch((uint8,uint128,uint128,uint16,uint16,uint16[5])[])"))

DEPTH_SELECTOR

The sole allowed ExecutionPricing entry point.

bytes4 private constant DEPTH_SELECTOR =
    bytes4(keccak256("publish(uint256,(uint128,uint128)[],(uint128,uint128)[])"))

Functions

constructor

Fix the writer and both publication destinations for this deployment.

The writer cannot be either destination, preventing target callbacks.

Notes:

  • security: Targets must contain code and be distinct from the writer and each other.

  • validation: Nonzero writer, deployed and distinct destinations.

  • state-changes: Sets immutable deployment bindings.

  • events: None.

  • errors: InvalidAddress on invalid bindings.

  • reentrancy: No external calls.

  • access: Deployment only.

  • oracle: No oracle reads.

constructor(address publisher, address price, address depth) ;

Parameters

NameTypeDescription
publisheraddressAuthorized publication account.
priceaddressSlippageStorage contract.
depthaddressExecutionPricing contract.

publishTogether

Forward both reports atomically, market summaries first.

Revert data is propagated unchanged. No ETH, delegatecall, generic calls or role management is exposed. A target revert rolls back both calls; a source silently skipped by SlippageStorage remains skipped.

Notes:

  • security: Fixed caller, targets and selectors; callbacks from targets cannot reenter.

  • validation: Caller and selectors here; report validation in each destination.

  • state-changes: Updates destination reports; no local storage writes.

  • events: Destination SlippageSourceUpdated and BookPublished events.

  • errors: NotAuthorized, InvalidParameter, and unmodified destination errors.

  • reentrancy: Target callbacks fail the immutable writer check.

  • access: Only the immutable writer.

  • oracle: Preserves both destinations' oracle and freshness validation.

function publishTogether(bytes calldata priceCall, bytes calldata depthCall) external;

Parameters

NameTypeDescription
priceCallbytesABI-encoded updateSlippageBatch call.
depthCallbytesABI-encoded publish call.

version

Return the semantic version of this contract.

Compile-time constant for deployment provenance.

Notes:

  • security: Read-only metadata.

  • validation: None.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: No external calls.

  • access: Public.

  • oracle: None.

function version() external pure override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string.

ReportPublicationBatcher

Git Source

Inherits: IVersioned

Title: ReportPublicationBatcher

Publishes any combination of market price, depth and reconciled capacity.

Fixed destinations and selectors. Reports fail independently; target events determine accepted data, since a successful price call can skip a source.

Notes:

  • security: Only the immutable writer can publish. Each subcall has a fixed gas budget, reserved before execution so estimation cannot starve later reports.

  • security-contact: team@quantillon.money

Constants

writer

Authorized publisher account.

address public immutable writer

priceStore

Market summary storage.

address public immutable priceStore

depthStore

Execution depth and hedge capacity storage.

address public immutable depthStore

PRICE_GAS

Upper gas allocation for at most two market sources.

uint256 public constant PRICE_GAS = 200_000

DEPTH_GAS

Allocation covers the publisher's ten levels per side, including cold storage.

uint256 public constant DEPTH_GAS = 1_100_000

CAPACITY_GAS

Upper gas allocation for a capacity acknowledgment.

uint256 public constant CAPACITY_GAS = 150_000

PRICE_SELECTOR

bytes4 private constant PRICE_SELECTOR =
    bytes4(keccak256("updateSlippageBatch((uint8,uint128,uint128,uint16,uint16,uint16[5])[])"))

DEPTH_SELECTOR

bytes4 private constant DEPTH_SELECTOR =
    bytes4(keccak256("publish(uint256,(uint128,uint128)[],(uint128,uint128)[])"))

CAPACITY_SELECTOR

bytes4 private constant CAPACITY_SELECTOR = bytes4(keccak256("acknowledge(uint256,uint256,uint256,uint256)"))

State Variables

lastPublicationAt

Block time of the last batch with a successful destination call.

uint256 public lastPublicationAt

Functions

constructor

Set permanent publisher and target addresses.

Constructor wiring is immutable and rejects overlapping publisher and destination addresses.

Notes:

  • security: No role grants or arbitrary targets are exposed.

  • validation: Rejects zero, non-contract, or overlapping addresses.

  • state-changes: Stores immutable writer and destination addresses.

  • events: None.

  • errors: InvalidAddress for invalid wiring.

  • reentrancy: No external calls.

  • access: Deployment only.

  • oracle: None.

constructor(address publisher, address price, address depth) ;

Parameters

NameTypeDescription
publisheraddressPublisher account, distinct from both destinations.
priceaddressDeployed price storage.
depthaddressDeployed execution pricing contract.

publishReports

Submit one, two or three independently validated reports.

Price then depth then capacity preserves the existing combined-publication order. Capacity never resets consumed depth; a later fresh book applies the target's rules.

Notes:

  • security: Rejects invalid selectors before any effects. Reverting reports do not undo valid reports. All-failed batches revert so preflight estimation rejects them.

  • validation: Requires at least one supported call and enough gas for the selected reports.

  • state-changes: Updates successful target reports and the publication timestamp.

  • events: Emits ReportsPublished and ReportRejected for failed subcalls.

  • errors: NotAuthorized, InvalidParameter, InsufficientReportGas, or NoSuccessfulReports.

  • reentrancy: Uses bounded low-level calls to immutable targets.

  • access: Restricted to the immutable writer.

  • oracle: Reads no oracle directly; forwards validated report calls.

function publishReports(bytes calldata priceCall, bytes calldata depthCall, bytes calldata capacityCall)
    external
    returns (uint8 succeeded);

Parameters

NameTypeDescription
priceCallbytesEncoded updateSlippageBatch, or empty to omit.
depthCallbytesEncoded publish, or empty to omit.
capacityCallbytesEncoded acknowledge, or empty to omit.

Returns

NameTypeDescription
succeededuint8Destination-call success mask; inspect target events for accepted reports.

_selector

function _selector(bytes calldata data, bytes4 expected) private pure;

_call

function _call(address target, bytes calldata data, uint256 budget, uint8 report) private returns (bool ok);

version

Semantic version of this separately deployed, non-upgradeable contract.

The value is embedded in bytecode for release traceability.

Notes:

  • security: No security implications; this is a pure constant getter.

  • validation: No input validation.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable.

  • access: Public.

  • oracle: None.

function version() external pure override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string.

Events

ReportsPublished

Masks use price=1, depth=2, capacity=4. Success denotes call success, not source acceptance.

event ReportsPublished(uint8 attempted, uint8 succeeded);

ReportRejected

First four revert bytes for a failed report; no unbounded return data is copied.

event ReportRejected(uint8 indexed report, bytes4 reason);

Errors

InsufficientReportGas

error InsufficientReportGas();

NoSuccessfulReports

error NoSuccessfulReports();

ISignedExecutionVault

Git Source

Functions

mintFee

Read the mint fee rate in 1e18 precision.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function mintFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

redemptionFee

Read the redemption fee rate in 1e18 precision.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function redemptionFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

paused

Read the vault pause state.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function paused() external view returns (bool);

Returns

NameTypeDescription
<none>boolValue defined by this accessor or calculation.

usdc

Read the configured collateral token address.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function usdc() external view returns (address);

Returns

NameTypeDescription
<none>addressValue defined by this accessor or calculation.

SignedExecutionPricing

Git Source

Inherits: AccessControl, EIP712, IExecutionPricing

Title: SignedExecutionPricing

Exact quotes with independently certified capacity and persistent admission accounting.

Non-upgradeable, vault-bound replacement. A settlement context must begin and end in one vault call.

Constants

QUOTE_SIGNER_ROLE

bytes32 public constant QUOTE_SIGNER_ROLE = keccak256("QUOTE_SIGNER_ROLE")

CAPACITY_SIGNER_ROLE

bytes32 public constant CAPACITY_SIGNER_ROLE = keccak256("CAPACITY_SIGNER_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

QUOTE_TYPEHASH

bytes32 public constant QUOTE_TYPEHASH = keccak256(
    "Quote(address user,address caller,uint8 action,uint256 amountIn,uint256 amountOut,uint256 observedAt,uint256 validAfter,uint256 validUntil,uint256 nonce,uint256 epoch,bytes32 callHash,bytes32 referenceHash)"
)

CAPACITY_TYPEHASH

bytes32 public constant CAPACITY_TYPEHASH = keccak256(
    "CapacityReport(uint256 acknowledgedBuy,uint256 acknowledgedSell,uint256 capacity,uint256 observedAt,uint256 sequence,uint256 epoch,uint256 canonicalBlock,bytes32 canonicalBlockHash)"
)

vault

address public immutable override vault

reserveRecipient

address public immutable reserveRecipient

referenceSource

SignedReferenceSource public immutable referenceSource

maxImpactBps

uint256 public immutable maxImpactBps

maxOutstanding

uint256 public immutable maxOutstanding

maxAge

uint256 public immutable maxAge

degradedHaircutBps

uint256 public immutable degradedHaircutBps

State Variables

mode

T.Mode public mode

epoch

uint256 public epoch = 1

admittedBuy

uint256 public admittedBuy

admittedSell

uint256 public admittedSell

acknowledgedBuy

uint256 public acknowledgedBuy

acknowledgedSell

uint256 public acknowledgedSell

marginCapacity

uint256 public marginCapacity

capacityObservedAt

uint256 public capacityObservedAt

capacitySequence

uint256 public capacitySequence

capacityHash

bytes32 public capacityHash

emergencyBudget

uint256 public emergencyBudget

usedNonces

mapping(address => mapping(uint256 => bool)) public usedNonces

activeQuote

T.Quote private activeQuote

active

bool public active

consumed

bool private consumed

emergencySettlement

bool private emergencySettlement

activeReference

uint256 private activeReference

activeDigest

bytes32 private activeDigest

Functions

constructor

Bind the vault, reference source and immutable execution risk limits.

Binds the EIP-712 domain and immutable safety limits at deployment.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Rejects zero or incompatible dependencies and out-of-range safety parameters.

  • state-changes: Sets immutable policy, initial mode and administrator role.

  • events: RoleGranted for the initial administrator.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Public.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

constructor(
    address admin,
    address boundVault,
    address source,
    address reserve,
    uint256 impact,
    uint256 outstandingLimit,
    uint256 age,
    uint256 haircut
) EIP712("Quantillon Execution", "1");

Parameters

NameTypeDescription
adminaddressAuthority administering roles and operating parameters.
boundVaultaddressVault allowed to prepare and consume execution contexts.
sourceaddressReference-source address, or snapshot source ID for the snapshot reader.
reserveaddressImmutable recipient of execution spread withdrawals.
impactuint256Maximum permitted execution impact in basis points.
outstandingLimituint256Maximum gross unacknowledged QEURO exposure.
ageuint256Maximum accepted report age in seconds.
haircutuint256Emergency redemption haircut in basis points.

onlyVault

modifier onlyVault() ;

supportsSignedExecution

Identify this module as requiring signed execution contexts.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function supportsSignedExecution() external pure returns (bool);

Returns

NameTypeDescription
<none>boolValue defined by this accessor or calculation.

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

quoteDigest

Hash an execution quote using this chain and module's EIP-712 domain.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function quoteDigest(T.Quote calldata q) public view returns (bytes32);

Parameters

NameTypeDescription
qT.QuoteExecution quote to hash.

Returns

NameTypeDescription
<none>bytes32Value defined by this accessor or calculation.

capacityDigest

Hash a capacity report using this chain and module's EIP-712 domain.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function capacityDigest(T.CapacityReport calldata r) public view returns (bytes32);

Parameters

NameTypeDescription
rT.CapacityReportSigned report containing its original observation, sequence and epoch.

Returns

NameTypeDescription
<none>bytes32Value defined by this accessor or calculation.

outstanding

Return unresolved admitted buys plus unresolved admitted sells in QEURO units.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function outstanding() public view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.

submitCapacity

Accept monotonic fill acknowledgments bound to canonical Base state.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Updates acknowledged exposure, capacity, sequence and original observation time.

  • events: HedgeAcknowledged.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Anyone may relay a valid capacity signature.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function submitCapacity(T.CapacityReport calldata r, bytes calldata signature) public;

Parameters

NameTypeDescription
rT.CapacityReportSigned report containing its original observation, sequence and epoch.
signaturebytesEIP-712 signature by the corresponding authorized signer.

prepare

Validate and prepare the operation before settlement.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Stores the active quote and consumes its nonce after report validation.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function prepare(address user, address caller, bytes calldata callData, T.Authorization calldata auth)
    external
    onlyVault;

Parameters

NameTypeDescription
useraddressOriginal payer whose nonce and settlement are bound.
calleraddressExecutor that must match the active quote.
callDatabytesComplete ABI-encoded operation, including route and output bounds.
authT.AuthorizationComplete execution, reference and capacity authorization.

prepareEmergency

Reserve the emergency budget for one redemption.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Decrements the emergency budget and initializes one redemption context.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function prepareEmergency(address caller, uint256 amount) external onlyVault;

Parameters

NameTypeDescription
calleraddressExecutor that must match the active quote.
amountuint256Amount in the token units of the selected operation.

requireContext

Require the active settlement to belong to the specified executor.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function requireContext(address caller) external view onlyVault;

Parameters

NameTypeDescription
calleraddressExecutor that must match the active quote.

finish

Close a consumed settlement or a permitted zero-yield harvest.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Clears the active settlement context.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function finish(bool allowNoConversion) external onlyVault;

Parameters

NameTypeDescription
allowNoConversionboolWhether an authorized zero-yield harvest may finish without minting.

consumeMint

Consume the exact mint or bounded yield authorization and admit its hedge exposure.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Increments admitted buy exposure and marks the quote consumed.

  • events: QuoteSettled.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function consumeMint(uint256 netUsdc, uint256 referencePrice)
    external
    override
    onlyVault
    returns (uint256 q, uint256 backing);

Parameters

NameTypeDescription
netUsdcuint256USDC available for conversion after protocol fees.
referencePriceuint256Validated EUR/USD reference in 1e18 precision.

Returns

NameTypeDescription
quint256Authorized QEURO output in eighteen-decimal units.
backinguint256Reference-valued backing in six-decimal USDC units.

consumeRedeem

Consume a redemption authorization while enforcing reference fees and spread limits.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Increments admitted sell exposure and marks the quote consumed.

  • events: QuoteSettled.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function consumeRedeem(uint256 qeuroIn, uint256 referencePrice)
    external
    override
    onlyVault
    returns (uint256 executionUsdc);

Parameters

NameTypeDescription
qeuroInuint256QEURO input in eighteen-decimal units.
referencePriceuint256Validated EUR/USD reference in 1e18 precision.

Returns

NameTypeDescription
executionUsdcuint256Execution-valued USDC before protocol redemption fees.

consumeLiquidation

Account for the admitted sell exposure of a budgeted liquidation redemption.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Increments admitted sell exposure and marks the emergency conversion consumed.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Configured vault only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function consumeLiquidation(uint256 qeuroIn) external onlyVault;

Parameters

NameTypeDescription
qeuroInuint256QEURO input in eighteen-decimal units.

setMode

Change operating mode and invalidate outstanding execution authorizations.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Updates mode and epoch, invalidates capacity freshness and selects reference mode.

  • events: ModeChanged and reference-mode events when changed.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Admin to enable Signed mode; admin or emergency role to stop normal execution.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function setMode(T.Mode next) external;

Parameters

NameTypeDescription
nextT.ModeRequested operating mode.

configureEmergencyBudget

Set an emergency budget only while paused and with no unacknowledged exposure.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Replaces the explicitly configured emergency budget.

  • events: EmergencyBudgetConfigured.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Default admin only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function configureEmergencyBudget(uint256 budget) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
budgetuint256Maximum emergency QEURO redemption amount in eighteen-decimal units.

withdrawReserve

Transfer execution spread to the immutable reserve recipient.

Execution contexts are single-use and cannot replace the vault's accounting guards.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Transfers module-held USDC to the configured recipient.

  • events: Underlying operation and token events when applicable.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Vault-only settlement and active-context checks constrain callbacks.

  • access: Default admin only.

  • oracle: Signed reference and reconciled capacity for normal conversion; separate emergency policy.

function withdrawReserve(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
amountuint256Amount in the token units of the selected operation.

_checkContext

function _checkContext(uint256 referencePrice) private view;

_admit

function _admit(uint256 quantity, bool buy) private;

_validateSelector

function _validateSelector(bytes4 selector, T.Action action) private pure;

Events

QuoteSettled

event QuoteSettled(
    bytes32 indexed quoteId, address indexed caller, T.Action action, uint256 amountIn, uint256 amountOut
);

HedgeAcknowledged

event HedgeAcknowledged(uint256 admittedBuy, uint256 admittedSell, uint256 capacity, uint256 observedAt);

ModeChanged

event ModeChanged(T.Mode mode, uint256 epoch);

EmergencyBudgetConfigured

event EmergencyBudgetConfigured(uint256 budget);

ISignedIndependentReference

Git Source

Independent reference source that never substitutes cached data for an invalid round.

Functions

peekEurUsdPrice

Read an independent reference, its original observation time and validity.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function peekEurUsdPrice() external view returns (uint256, uint256, bool);

Returns

NameTypeDescription
<none>uint256Value defined by this accessor or calculation.
<none>uint256Value defined by this accessor or calculation.
<none>boolValue defined by this accessor or calculation.

SignedReferenceSource

Git Source

Inherits: AccessControl, EIP712

Title: SignedReferenceSource

Pull-delivered market reference compatible with HyperliquidEurUsdOracle's snapshot reader.

The existing oracle retains price bounds, deviation checks, USDC validation and router semantics.

Constants

REFERENCE_SIGNER_ROLE

bytes32 public constant REFERENCE_SIGNER_ROLE = keccak256("REFERENCE_SIGNER_ROLE")

EMERGENCY_CONTROLLER_ROLE

bytes32 public constant EMERGENCY_CONTROLLER_ROLE = keccak256("EMERGENCY_CONTROLLER_ROLE")

REPORT_TYPEHASH

bytes32 public constant REPORT_TYPEHASH =
    keccak256("ReferenceReport(uint256 price,uint256 observedAt,uint256 sequence,uint256 epoch)")

independentReference

ISignedIndependentReference public immutable independentReference

maxAge

uint256 public immutable maxAge

maxReferenceAge

uint256 public immutable maxReferenceAge

normalDivergenceBps

uint256 public immutable normalDivergenceBps

offHoursDivergenceBps

uint256 public immutable offHoursDivergenceBps

State Variables

epoch

uint256 public epoch = 1

sequence

uint256 public sequence

observedAt

uint256 public observedAt

price

uint256 public price

reportHash

bytes32 public reportHash

emergency

bool public emergency

Functions

constructor

Bind the reference authority and immutable freshness and divergence limits.

Binds the EIP-712 domain and immutable safety limits at deployment.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Rejects zero or incompatible dependencies and out-of-range safety parameters.

  • state-changes: Sets immutable policy, initial mode and administrator role.

  • events: RoleGranted for the initial administrator.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Independent price reads use static calls.

  • access: Public.

  • oracle: Independent EUR/USD validation; accepted reports preserve original market timestamps.

constructor(
    address admin,
    address independent,
    uint256 age,
    uint256 referenceAge,
    uint256 normalBps,
    uint256 offHoursBps
) EIP712("Quantillon Reference", "1");

Parameters

NameTypeDescription
adminaddressAuthority administering roles and operating parameters.
independentaddressContract supplying independently validated EUR/USD observations.
ageuint256Maximum accepted report age in seconds.
referenceAgeuint256Maximum independent-reference age in seconds.
normalBpsuint256Reference divergence bound during normal trading hours.
offHoursBpsuint256Reference divergence bound outside normal trading hours.

version

Return the semantic version of this implementation.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function version() external pure returns (string memory);

Returns

NameTypeDescription
<none>stringValue defined by this accessor or calculation.

digest

Hash a market-reference report using this chain and source's EIP-712 domain.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function digest(T.ReferenceReport calldata r) public view returns (bytes32);

Parameters

NameTypeDescription
rT.ReferenceReportSigned report containing its original observation, sequence and epoch.

Returns

NameTypeDescription
<none>bytes32Value defined by this accessor or calculation.

submit

Authenticate a reference report, updating the cache only for newer observations.

Original observation timestamps remain authoritative; signature replay never refreshes them.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Stores price, original observation, sequence and digest.

  • events: ReferenceAccepted for a new observation.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Independent price reads use static calls.

  • access: Anyone may relay a valid reference signature.

  • oracle: Independent EUR/USD validation; accepted reports preserve original market timestamps.

function submit(T.ReferenceReport calldata r, bytes calldata signature) external returns (bytes32 hash);

Parameters

NameTypeDescription
rT.ReferenceReportSigned report containing its original observation, sequence and epoch.
signaturebytesEIP-712 signature by the corresponding authorized signer.

Returns

NameTypeDescription
hashbytes32EIP-712 digest of the accepted report.

setEmergency

Change reference mode and invalidate prior reference authorizations.

Original observation timestamps remain authoritative; signature replay never refreshes them.

Notes:

  • security: Validates domain-specific permissions and configured risk bounds.

  • validation: Enforces the checks described for this operation; invalid authorization reverts.

  • state-changes: Updates emergency state and reference epoch.

  • events: ReferenceEpochChanged when the mode changes.

  • errors: Reverts on invalid inputs, permissions or failed downstream calls.

  • reentrancy: Independent price reads use static calls.

  • access: Emergency-controller role only.

  • oracle: Independent EUR/USD validation; accepted reports preserve original market timestamps.

function setEmergency(bool enabled) external onlyRole(EMERGENCY_CONTROLLER_ROLE);

Parameters

NameTypeDescription
enabledboolEnabled-vault mapping, or requested emergency state for the reference source.

getSlippageBySource

Read a compatible snapshot with its original market or independent-reference timestamp.

Returns the declared configuration or derived value without updating state.

Notes:

  • security: Read-only; does not authorize settlement.

  • validation: Uses the declared input types; target interface calls may revert.

  • state-changes: None.

  • events: None.

  • errors: Propagates invalid input or target read failures.

  • reentrancy: Read-only.

  • access: Public.

  • oracle: No fresh observation is created; reference getters expose existing source data.

function getSlippageBySource(uint8 source)
    external
    view
    returns (ISlippageStorage.SlippageSnapshot memory snapshot);

Parameters

NameTypeDescription
sourceuint8Reference-source address, or snapshot source ID for the snapshot reader.

Returns

NameTypeDescription
snapshotISlippageStorage.SlippageSnapshotPrice and original timestamp in the snapshot interface.

_independent

function _independent() private view returns (uint256 p, uint256 time);

_validateIndependent

function _validateIndependent(uint256 candidate) private view;

Events

ReferenceAccepted

event ReferenceAccepted(bytes32 indexed digest, uint256 price, uint256 observedAt, uint256 sequence);

ReferenceEpochChanged

event ReferenceEpochChanged(uint256 epoch, bool emergency);

SlippageStorage

Git Source

Inherits: ISlippageStorage, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: SlippageStorage

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

On-chain storage for EUR/USD order book slippage data published by the Slippage Monitor service

Key features:

  • WRITER_ROLE publishes slippage snapshots (mid price, spread, depth, worst-case bps)
  • Rate-limited writes: rejects updates within minUpdateInterval unless deviation > threshold
  • MANAGER_ROLE configures interval and threshold parameters
  • Pausable by EMERGENCY_ROLE
  • UUPS upgradeable

Note: security-contact: team@quantillon.money

Constants

SOURCE_LIGHTER

Source ID for Lighter DEX (maps to legacy _snapshot slot for backward compat)

uint8 public constant SOURCE_LIGHTER = 0

SOURCE_HYPERLIQUID

Source ID for Hyperliquid DEX

uint8 public constant SOURCE_HYPERLIQUID = 1

WRITER_ROLE

Role for the off-chain publisher service wallet

bytes32 public constant WRITER_ROLE = keccak256("WRITER_ROLE")

MANAGER_ROLE

Role for config management (interval, threshold)

bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency pause/unpause

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for UUPS upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_UPDATE_INTERVAL

Max allowed minUpdateInterval (1 hour)

uint48 public constant MAX_UPDATE_INTERVAL = 3600

MAX_DEVIATION_THRESHOLD

Max allowed deviation threshold (500 bps = 5%)

uint16 public constant MAX_DEVIATION_THRESHOLD = 500

TIME_PROVIDER

Shared time provider for deterministic timestamp reads

TimeProvider public immutable TIME_PROVIDER

State Variables

_snapshot

Current slippage snapshot (2 packed storage slots)

SlippageSnapshot private _snapshot

minUpdateInterval

Minimum seconds between successive updates (rate limit)

uint48 public override minUpdateInterval

deviationThresholdBps

Deviation in bps that bypasses rate limit for immediate updates

uint16 public override deviationThresholdBps

treasury

Treasury address for recovery functions

address public treasury

_sourceSnapshots

Snapshots for sources other than SOURCE_LIGHTER (which uses _snapshot for compat)

mapping(uint8 sourceId => SlippageSnapshot) private _sourceSnapshots

enabledSources

Bitmask of enabled sources: bit N = source N enabled. 0x03 = both Lighter + Hyperliquid.

uint8 public override enabledSources

minMidPrice

Absolute lower bound for an accepted midPrice (18 dec). 0 with maxMidPrice==0 = band disabled.

uint128 public minMidPrice

maxMidPrice

Absolute upper bound for an accepted midPrice (18 dec). 0 = band check disabled.

uint128 public maxMidPrice

maxMidDeviationBps

Max per-write deviation (bps) vs the source's last stored mid. 0 = deviation check disabled.

uint16 public maxMidDeviationBps

maxMidDriftBps

Maximum cumulative mid-price drift allowed during one rolling window.

uint16 public maxMidDriftBps

midDriftWindow

Rolling window for cumulative mid-price drift in seconds.

uint32 public midDriftWindow

_midDriftAnchors

Cumulative drift anchors by source id.

mapping(uint8 sourceId => MidDriftAnchor) private _midDriftAnchors

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Disables initializers to prevent direct implementation contract use

Called once at deployment time by the EVM. Prevents the implementation contract from being initialized directly (only proxy is initializable).

Notes:

  • security: Calls _disableInitializers() to prevent re-initialization attacks

  • validation: No input validation required

  • state-changes: Disables all initializer functions permanently

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - constructor

  • access: Public - called once at deployment

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderShared protocol time provider used for deterministic timestamps

initialize

Initialize the SlippageStorage contract

Sets up roles, rate-limit parameters, and treasury. Calls OpenZeppelin initializers for AccessControl, Pausable, and UUPSUpgradeable. Admin receives DEFAULT_ADMIN_ROLE, MANAGER_ROLE, EMERGENCY_ROLE, and UPGRADER_ROLE.

Notes:

  • security: Validates admin, writer, and treasury are non-zero; enforces config bounds

  • validation: Validates admin != address(0), writer != address(0), treasury != address(0), minInterval <= MAX_UPDATE_INTERVAL, deviationThreshold <= MAX_DEVIATION_THRESHOLD

  • state-changes: Grants roles, sets minUpdateInterval, deviationThresholdBps, treasury

  • events: No events emitted (OpenZeppelin initializers emit no events)

  • errors: Reverts with ZeroAddress if admin/writer/treasury is zero; reverts with ConfigValueTooHigh if interval or threshold exceeds max

  • reentrancy: Protected by initializer modifier (callable only once)

  • access: Public - only callable once during proxy deployment

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address writer,
    uint48 minInterval,
    uint16 deviationThreshold,
    address _treasury,
    uint8 initialEnabledSources
) external override initializer;

Parameters

NameTypeDescription
adminaddressAddress receiving DEFAULT_ADMIN_ROLE and all management roles
writeraddressAddress receiving WRITER_ROLE (the off-chain publisher service wallet)
minIntervaluint48Minimum seconds between successive writes (0..MAX_UPDATE_INTERVAL)
deviationThresholduint16Deviation in bps that bypasses rate limit (0..MAX_DEVIATION_THRESHOLD)
_treasuryaddressTreasury address for token/ETH recovery
initialEnabledSourcesuint8Bitmask of initially enabled sources (0x01=Lighter, 0x02=Hyperliquid, 0x03=both)

updateSlippage

Publish a new slippage snapshot on-chain

Rate-limited: if within minUpdateInterval since last update, only allows the write when |newWorstCaseBps - lastWorstCaseBps| > deviationThresholdBps. First update always succeeds (timestamp == 0 means no prior data). Packs all fields into a single SlippageSnapshot struct for efficient storage.

Notes:

  • security: Requires WRITER_ROLE; blocked when paused; rate-limited by minUpdateInterval

  • validation: Checks elapsed time since last update; if within interval, validates |worstCaseBps - lastWorstCaseBps| > deviationThresholdBps

  • state-changes: Overwrites _snapshot with new values, timestamp, and block number

  • events: Emits SlippageUpdated(midPrice, worstCaseBps, spreadBps, depthEur, timestamp)

  • errors: Reverts with RateLimitTooHigh if within interval and deviation is below threshold

  • reentrancy: Not protected - no external calls made during execution

  • access: Restricted to WRITER_ROLE; blocked when contract is paused

  • oracle: No on-chain oracle dependency; data is pushed by the off-chain Slippage Monitor

function updateSlippage(
    uint128 midPrice,
    uint128 depthEur,
    uint16 worstCaseBps,
    uint16 spreadBps,
    uint16[5] calldata bucketBps
) external override onlyRole(WRITER_ROLE) whenNotPaused;

Parameters

NameTypeDescription
midPriceuint128EUR/USD mid price (18 decimals)
depthEuruint128Total ask depth in EUR (18 decimals)
worstCaseBpsuint16Worst-case slippage across buckets (bps)
spreadBpsuint16Bid-ask spread (bps)
bucketBpsuint16[5]Per-size slippage in bps, fixed order: [10k, 50k, 100k, 250k, 1M]

updateSlippageBatch

Publish slippage snapshots for multiple sources in a single transaction

Sources disabled in enabledSources bitmask are silently skipped (no revert). Rate-limited per source independently: within-interval updates are skipped unless |diff| > deviationThresholdBps. Lighter source (sourceId=0) writes to the legacy _snapshot slot for backward compatibility with getSlippage().

Notes:

  • security: Requires WRITER_ROLE; blocked when paused

  • validation: Per-source rate limit: skips (does not revert) if within interval and deviation <= threshold

  • state-changes: Writes each enabled source's snapshot; Lighter updates _snapshot for backward compat

  • events: Emits SlippageSourceUpdated for each source actually written

  • errors: No explicit reverts for rate-limited or disabled sources (silently skipped)

  • reentrancy: Not protected - no external calls made during execution

  • oracle: No on-chain oracle dependency; data is pushed by the off-chain Slippage Monitor

  • access: Restricted to WRITER_ROLE; blocked when contract is paused

function updateSlippageBatch(SourceUpdate[] calldata updates)
    external
    override
    onlyRole(WRITER_ROLE)
    whenNotPaused;

Parameters

NameTypeDescription
updatesSourceUpdate[]Array of per-source snapshot inputs

setEnabledSources

Update the minimum interval between successive slippage writes

Update the bitmask of sources enabled for storage in updateSlippageBatch

Allows the manager to tighten or relax the rate limit. Setting to 0 effectively disables the rate limit; MAX_UPDATE_INTERVAL caps it at 1 hour.

Bit 0 = SOURCE_LIGHTER, Bit 1 = SOURCE_HYPERLIQUID. 0x03 enables both. Disabled sources are silently skipped in batch writes without reverting.

Notes:

  • security: Requires MANAGER_ROLE; enforces upper bound MAX_UPDATE_INTERVAL

  • validation: Validates newInterval <= MAX_UPDATE_INTERVAL

  • state-changes: Updates minUpdateInterval state variable

  • events: Emits ConfigUpdated("minUpdateInterval", oldValue, newValue)

  • errors: Reverts with ConfigValueTooHigh if newInterval > MAX_UPDATE_INTERVAL

  • reentrancy: Not protected - no external calls made

  • access: Restricted to MANAGER_ROLE

  • oracle: No oracle dependencies

  • security: Requires MANAGER_ROLE

  • validation: No additional validation; all uint8 values accepted

  • state-changes: Updates enabledSources state variable

  • events: Emits EnabledSourcesUpdated(oldMask, newMask)

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls made

  • oracle: No oracle dependencies

  • access: Restricted to MANAGER_ROLE

function setEnabledSources(uint8 mask) external override onlyRole(MANAGER_ROLE);

Parameters

NameTypeDescription
maskuint8New bitmask (0x01=Lighter only, 0x02=Hyperliquid only, 0x03=both)

setMinUpdateInterval

Update the minimum interval between successive slippage writes

Allows the manager to tighten or relax the rate limit. Setting to 0 effectively disables the rate limit; MAX_UPDATE_INTERVAL caps it at 1 hour.

Notes:

  • security: Requires MANAGER_ROLE; enforces upper bound MAX_UPDATE_INTERVAL

  • validation: Validates newInterval <= MAX_UPDATE_INTERVAL

  • state-changes: Updates minUpdateInterval state variable

  • events: Emits ConfigUpdated("minUpdateInterval", oldValue, newValue)

  • errors: Reverts with ConfigValueTooHigh if newInterval > MAX_UPDATE_INTERVAL

  • reentrancy: Not protected - no external calls made

  • oracle: No oracle dependencies

  • access: Restricted to MANAGER_ROLE

function setMinUpdateInterval(uint48 newInterval) external override onlyRole(MANAGER_ROLE);

Parameters

NameTypeDescription
newIntervaluint48New minimum interval in seconds (0..MAX_UPDATE_INTERVAL)

setDeviationThreshold

Update the worst-case bps deviation threshold that bypasses the rate limit

When the absolute difference between the new worstCaseBps and the stored worstCaseBps exceeds this threshold, the rate limit is bypassed and the update proceeds immediately regardless of minUpdateInterval.

Notes:

  • security: Requires MANAGER_ROLE; enforces upper bound MAX_DEVIATION_THRESHOLD (500 bps)

  • validation: Validates newThreshold <= MAX_DEVIATION_THRESHOLD

  • state-changes: Updates deviationThresholdBps state variable

  • events: Emits ConfigUpdated("deviationThresholdBps", oldValue, newValue)

  • errors: Reverts with ConfigValueTooHigh if newThreshold > MAX_DEVIATION_THRESHOLD

  • reentrancy: Not protected - no external calls made

  • access: Restricted to MANAGER_ROLE

  • oracle: No oracle dependencies

function setDeviationThreshold(uint16 newThreshold) external override onlyRole(MANAGER_ROLE);

Parameters

NameTypeDescription
newThresholduint16New deviation threshold in bps (0..MAX_DEVIATION_THRESHOLD)

setMidPriceGuards

Configure the writer-side midPrice guards.

Set band and per-write deviation for the published EUR/USD mid. Pass maxMid=0 to disable the band and devBps=0 to disable the deviation check. Must be called after an upgrade to activate the guards (they default off).

Notes:

  • security: Restricted to MANAGER_ROLE

  • validation: Requires minMid <= maxMid when the band is enabled; devBps bounded

  • state-changes: Sets minMidPrice/maxMidPrice/maxMidDeviationBps

  • events: Emits ConfigUpdated for each changed field

  • errors: ConfigValueTooHigh / InvalidPrice on bad bounds

  • reentrancy: No external calls

  • access: MANAGER_ROLE

  • oracle: No oracle dependencies

function setMidPriceGuards(uint128 minMid, uint128 maxMid, uint16 devBps) external onlyRole(MANAGER_ROLE);

Parameters

NameTypeDescription
minMiduint128Absolute lower bound (18 dec)
maxMiduint128Absolute upper bound (18 dec); 0 disables the band
devBpsuint16Max per-write deviation vs the source's last mid; 0 disables it

setMidDriftGuard

Configures cumulative mid-price drift protection.

Applies the same rolling-window semantics to single and batch updates.

Notes:

  • security: Restricted to MANAGER_ROLE and bounded by protocol limits.

  • validation: Zero disables the guard; nonzero windows must be within one hour.

  • state-changes: Updates cumulative drift configuration.

  • events: Emits ConfigUpdated for both values.

  • errors: Reverts with ConfigValueTooHigh for invalid values.

  • reentrancy: No external calls.

  • access: MANAGER_ROLE.

  • oracle: No oracle dependencies.

function setMidDriftGuard(uint16 maxDriftBps, uint32 windowSeconds) external onlyRole(MANAGER_ROLE);

Parameters

NameTypeDescription
maxDriftBpsuint16Maximum drift from the rolling anchor in basis points.
windowSecondsuint32Rolling window in seconds.

_midWithinDriftGuard

Checks cumulative movement against the active rolling anchor.

Returns true when the guard is disabled or the source window has expired.

Notes:

  • security: Limits repeated same-block and short-window price walks.

  • validation: Uses checked arithmetic and source-specific anchors.

  • state-changes: None.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Internal.

  • oracle: None.

function _midWithinDriftGuard(uint8 sourceId, uint128 lastMid, uint128 newMid, uint48 nowTs)
    internal
    view
    returns (bool);

Parameters

NameTypeDescription
sourceIduint8Price source identifier.
lastMiduint128Previously stored mid price.
newMiduint128Candidate mid price.
nowTsuint48Current timestamp.

Returns

NameTypeDescription
<none>boolTrue when cumulative drift remains within the configured bound.

_midWithinGuards

Whether a candidate midPrice passes the configured writer-side guards.

Returns true when guards are disabled (default). Enforces the absolute band (when maxMidPrice != 0) and the per-write deviation vs lastMid (when maxMidDeviationBps != 0 and a baseline exists).

Notes:

  • security: Pure guard logic over configured bounds; no external calls

  • validation: Band and deviation checks are each opt-in via config

  • state-changes: None - view function

  • events: None

  • errors: None - returns a bool

  • reentrancy: Not applicable - view function

  • access: Internal

  • oracle: No oracle dependencies

function _midWithinGuards(uint128 lastMid, uint128 newMid) internal view returns (bool);

Parameters

NameTypeDescription
lastMiduint128The source's currently stored mid (0 when no baseline yet)
newMiduint128The candidate mid to validate (18 decimals)

Returns

NameTypeDescription
<none>boolTrue if the candidate is acceptable (or guards are disabled)

_recordMidDrift

Records a new rolling drift anchor when the current window expires.

Disabled when either drift configuration value is zero.

Notes:

  • security: Anchors only accepted writer prices.

  • validation: Ignores zero prices and disabled guards.

  • state-changes: Updates the source anchor mapping.

  • events: None.

  • errors: None.

  • reentrancy: None.

  • access: Internal.

  • oracle: None.

function _recordMidDrift(uint8 sourceId, uint128 newMid, uint48 nowTs) internal;

Parameters

NameTypeDescription
sourceIduint8Price source identifier.
newMiduint128Accepted mid price.
nowTsuint48Current timestamp.

pause

Pause the contract, blocking all slippage updates

Once paused, updateSlippage will revert with a Paused error until unpaused. Used in emergency scenarios (e.g. off-chain service malfunction).

Notes:

  • security: Requires EMERGENCY_ROLE; prevents unauthorized pausing

  • validation: No input validation required

  • state-changes: Sets OpenZeppelin Pausable internal paused flag to true

  • events: Emits Paused(account) from OpenZeppelin PausableUpgradeable

  • errors: No errors thrown if already unpaused (OZ handles idempotently)

  • reentrancy: Not protected - no external calls made

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function pause() external override onlyRole(EMERGENCY_ROLE);

unpause

Unpause the contract, resuming slippage updates

Restores normal operation after an emergency pause. The WRITER_ROLE can immediately publish new snapshots once unpaused.

Notes:

  • security: Requires EMERGENCY_ROLE; prevents unauthorized unpausing

  • validation: No input validation required

  • state-changes: Sets OpenZeppelin Pausable internal paused flag to false

  • events: Emits Unpaused(account) from OpenZeppelin PausableUpgradeable

  • errors: No errors thrown if already unpaused (OZ handles idempotently)

  • reentrancy: Not protected - no external calls made

  • access: Restricted to EMERGENCY_ROLE

  • oracle: No oracle dependencies

function unpause() external override onlyRole(EMERGENCY_ROLE);

getSlippage

Get the full current slippage snapshot

Returns the entire _snapshot struct including midPrice, depthEur, worstCaseBps, spreadBps, timestamp, blockNumber, and all bucketBps. Returns a zero-valued struct if updateSlippage has never been called.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored state only

function getSlippage() external view override returns (SlippageSnapshot memory snapshot);

Returns

NameTypeDescription
snapshotSlippageSnapshotThe latest SlippageSnapshot stored on-chain

getBucketBps

Get per-bucket slippage in bps in canonical size order

Returns buckets in fixed order: [10k EUR, 50k EUR, 100k EUR, 250k EUR, 1M EUR]. All values are zero if updateSlippage has never been called.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored state only

function getBucketBps() external view override returns (uint16[5] memory bucketBps);

Returns

NameTypeDescription
bucketBpsuint16[5]Array of 5 slippage values in bps for each order size bucket

getSlippageAge

Get seconds elapsed since the last on-chain slippage update

Returns 0 if no update has ever been published (timestamp == 0). Consumers can use this to assess data freshness before relying on it.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • access: Public - no restrictions

  • oracle: No oracle dependencies - reads stored timestamp only

function getSlippageAge() external view override returns (uint256 age);

Returns

NameTypeDescription
ageuint256Seconds since last updateSlippage call, or 0 if never updated

getSlippageBySource

Get the full slippage snapshot for a specific source

sourceId=0 (SOURCE_LIGHTER) reads from the legacy _snapshot slot. Other sourceIds read from _sourceSnapshots mapping. Returns a zero-valued struct if no data has been published for that source.

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • oracle: No oracle dependencies - reads stored state only

  • access: Public - no restrictions

function getSlippageBySource(uint8 sourceId) external view override returns (SlippageSnapshot memory snapshot);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_LIGHTER=0, SOURCE_HYPERLIQUID=1)

Returns

NameTypeDescription
snapshotSlippageSnapshotThe latest SlippageSnapshot for the given source

getSlippageAgeBySource

Get seconds elapsed since the last on-chain update for a specific source

Returns 0 if no update has ever been published for the source (timestamp == 0).

Notes:

  • security: No security concerns - read-only view function

  • validation: No input validation required

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - view function

  • oracle: No oracle dependencies - reads stored timestamp only

  • access: Public - no restrictions

function getSlippageAgeBySource(uint8 sourceId) external view override returns (uint256 age);

Parameters

NameTypeDescription
sourceIduint8Source identifier (SOURCE_LIGHTER=0, SOURCE_HYPERLIQUID=1)

Returns

NameTypeDescription
ageuint256Seconds since last update for that source, or 0 if never updated

recoverToken

Recover ERC20 tokens accidentally sent to this contract

Transfers the specified token amount to the treasury address using TreasuryRecoveryLibrary. Use to rescue tokens that were mistakenly sent.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE; prevents unauthorized token withdrawals

  • validation: Implicitly validates via SafeERC20 transfer

  • state-changes: No internal state changes; transfers token balance externally

  • events: No events emitted from this contract

  • errors: Reverts if transfer fails (SafeERC20 revert)

  • reentrancy: Not protected - external ERC20 call; admin-only mitigates risk

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverToken(address token, uint256 amount) external override onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressERC20 token contract address to recover
amountuint256Amount of tokens to transfer to treasury (token decimals)

recoverETH

Recover ETH accidentally sent to this contract

Transfers the entire ETH balance to the treasury address using TreasuryRecoveryLibrary. The receive() function allows ETH to accumulate.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE; prevents unauthorized ETH withdrawals

  • validation: No input validation required; uses address(this).balance

  • state-changes: No internal state changes; transfers ETH balance externally

  • events: Emits ETHRecovered(treasury, amount)

  • errors: Reverts if ETH transfer fails

  • reentrancy: Not protected - external ETH transfer; admin-only mitigates risk

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverETH() external override onlyRole(DEFAULT_ADMIN_ROLE);

updateTreasury

Update the treasury address used for token/ETH recovery

The treasury is the destination for recoverToken and recoverETH calls. Must be a non-zero address to prevent accidental loss of recovered funds.

Notes:

  • security: Requires DEFAULT_ADMIN_ROLE; validates non-zero address

  • validation: Validates _treasury != address(0) via CommonValidationLibrary

  • state-changes: Updates the treasury state variable

  • events: Emits TreasuryUpdated(_treasury)

  • errors: Reverts with ZeroAddress if _treasury is address(0)

  • reentrancy: Not protected - no external calls made

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address (must be non-zero)

_authorizeUpgrade

Authorize a UUPS proxy upgrade to a new implementation

Called internally by UUPSUpgradeable.upgradeTo/upgradeToAndCall. Validates the new implementation address is non-zero before authorizing.

Notes:

  • security: Requires UPGRADER_ROLE; validates newImplementation is non-zero

  • validation: Validates newImplementation != address(0)

  • state-changes: No state changes in this function (upgrade handled by UUPS base)

  • events: No events emitted from this function

  • errors: Reverts with ZeroAddress if newImplementation is address(0)

  • reentrancy: Not protected - internal function; called within upgrade transaction

  • access: Restricted to UPGRADER_ROLE

  • oracle: No oracle dependencies

function _authorizeUpgrade(address newImplementation) internal view override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation contract

receive

Accept ETH sent directly to the contract

Allows the contract to receive ETH so that recoverETH can retrieve it. Used primarily for recovery testing to simulate accidental ETH deposits.

Notes:

  • security: No restrictions - any address can send ETH; admin can recover via recoverETH

  • validation: No input validation required

  • state-changes: No state changes - ETH balance increases implicitly

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not applicable - receive function

  • access: Public - no restrictions

  • oracle: No oracle dependencies

receive() external payable;

Structs

MidDriftAnchor

Per-source cumulative drift anchor.

struct MidDriftAnchor {
    uint128 anchorMid;
    uint48 windowStart;
}

IStorkFeed

Git Source

Stork Network oracle feed interface

This interface is based on Stork's EVM contract API VERIFICATION STATUS: ✅ Function getTemporalNumericValueV1 - Verified matches Stork's contract ✅ Struct TemporalNumericValue - Verified matches Stork's contract ✅ Decimals handling - Stork feeds use 18 decimals (constant, no function needed) NOTE: Stork's official SDK uses interface name "IStork" instead of "IStorkFeed", but the function signatures are identical. This interface should work correctly. IMPORTANT: Stork's contract does NOT have a decimals() function. Stork feeds use 18 decimals precision (value is multiplied by 10^18). We use constant STORK_FEED_DECIMALS = 18 instead of calling decimals(). See docs/STORK_INTERFACE_VERIFICATION.md for detailed verification Resources:

  • Documentation: https://docs.storkengine.com/contract-apis/evm
  • Contract Addresses: https://docs.stork.network/resources/contract-addresses/evm
  • Asset ID Registry: https://docs.stork.network/resources/asset-id-registry
  • GitHub: https://github.com/Stork-Oracle/stork-external
  • Official SDK: storknetwork/stork-evm-sdk (npm package) NOTE: Stork also provides Chainlink and Pyth adapters that may be easier to integrate. Consider using StorkChainlinkAdapter if you want to use Chainlink's familiar interface.

Note: security-contact: team@quantillon.money

Functions

getTemporalNumericValueV1

Gets the latest temporal numeric value for a given feed ID

Feed IDs are specific to each price pair (e.g., EUR/USD, USDC/USD) Obtain feed IDs from Stork's Asset ID Registry: https://docs.stork.network/resources/asset-id-registry ✅ Verified: Function signature matches Stork's contract

Notes:

  • security: Interface function - no security implications

  • validation: No validation - interface definition

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Interface for Stork feed contract

function getTemporalNumericValueV1(bytes32 id) external view returns (TemporalNumericValue memory);

Parameters

NameTypeDescription
idbytes32The feed ID (bytes32 identifier for the price feed)

Returns

NameTypeDescription
<none>TemporalNumericValueThe temporal numeric value containing price and timestamp

Structs

TemporalNumericValue

Temporal numeric value structure returned by Stork feeds

Verified to match Stork's StorkStructs.TemporalNumericValue

struct TemporalNumericValue {
    int256 value;
    uint256 timestamp;
}

Properties

NameTypeDescription
valueint256The price value (can be negative for some feeds)
timestampuint256The timestamp when the value was last updated

StorkOracle

Git Source

Inherits: IStorkOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable, IVersioned

Title: StorkOracle

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

EUR/USD and USDC/USD price manager for Quantillon Protocol using Stork Network

Key features:

  • Fetch EUR/USD price from Stork Network
  • Validate USDC/USD (should remain close to $1.00)
  • Circuit breakers against outlier prices
  • Fallbacks in case of oracle outage
  • Data freshness checks

DEPLOYMENT REQUIREMENTS: Before deploying, you must obtain the following from Stork Network:

  1. Stork contract address on Base mainnet (the main Stork oracle contract)
  2. EUR/USD feed ID (bytes32 identifier for EUR/USD price feed)
  3. USDC/USD feed ID (bytes32 identifier for USDC/USD price feed) How to obtain:
  • Visit Stork's data feeds: https://data.stork.network/
  • Search for "EUR/USD" and "USDC/USD" feeds
  • Contact Stork support for Base mainnet contract addresses: Discord: https://discord.com (Stork Network) Documentation: https://docs.stork.network/ Email: support at stork.network (if available) ALTERNATIVE: Consider using Stork's Chainlink adapter for easier integration:
  • GitHub: https://github.com/Stork-Oracle/stork-external
  • This would allow using Chainlink's familiar interface with Stork data

Note: security-contact: team@quantillon.money

Constants

ORACLE_MANAGER_ROLE

Role to manage oracle configurations

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency actions

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

UPGRADER_ROLE

Role for contract upgrades

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

MAX_PRICE_STALENESS

Maximum duration before a price is considered stale (1 hour)

3600 seconds = reasonable limit for real-time DeFi

uint256 public constant MAX_PRICE_STALENESS = 3600

MAX_PRICE_DEVIATION

Maximum allowed deviation from previous price (5%)

500 basis points = 5% in basis points (500/10000)

uint256 public constant MAX_PRICE_DEVIATION = 500

BASIS_POINTS

Basis for basis points calculations

uint256 public constant BASIS_POINTS = 10000

MAX_TIMESTAMP_DRIFT

Maximum timestamp drift tolerance (15 minutes)

Prevents timestamp manipulation attacks by miners

uint256 public constant MAX_TIMESTAMP_DRIFT = 900

STORK_FEED_DECIMALS

Stork price feed decimals (constant)

Stork feeds use 18 decimals precision (value is multiplied by 10^18) This is verified based on Stork's documentation

uint8 public constant STORK_FEED_DECIMALS = 18

DEV_MODE_DELAY

Minimum delay before a proposed dev-mode change takes effect

uint256 public constant DEV_MODE_DELAY = 48 hours

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

State Variables

eurUsdPriceFeed

Interface to Stork EUR/USD price feed

IStorkFeed public eurUsdPriceFeed

usdcUsdPriceFeed

Interface to Stork USDC/USD price feed

Used for USDC price validation and cross-checking

IStorkFeed public usdcUsdPriceFeed

treasury

Treasury address for ETH recovery

SECURITY: Only this address can receive ETH from recoverETH function

address public treasury

eurUsdFeedId

EUR/USD feed ID for Stork

bytes32 public eurUsdFeedId

usdcUsdFeedId

USDC/USD feed ID for Stork

bytes32 public usdcUsdFeedId

minEurUsdPrice

Minimum accepted EUR/USD price (lower circuit breaker)

Initialized to 0.80 USD per EUR (extreme crisis)

uint256 public minEurUsdPrice

maxEurUsdPrice

Maximum accepted EUR/USD price (upper circuit breaker)

Initialized to 1.40 USD per EUR (extreme scenario)

uint256 public maxEurUsdPrice

lastValidEurUsdPrice

Last valid EUR/USD price recorded (18 decimals)

Used as fallback if oracle is down

uint256 public lastValidEurUsdPrice

lastPriceUpdateTime

Timestamp of the last valid price update

uint256 public lastPriceUpdateTime

lastPriceUpdateBlock

Block number of the last valid price update

Used for block-based staleness checks to prevent timestamp manipulation

uint256 public lastPriceUpdateBlock

circuitBreakerTriggered

Circuit breaker status (true = triggered, fixed prices)

bool public circuitBreakerTriggered

usdcToleranceBps

USDC/USD tolerance (USDC should remain close to $1.00)

200 basis points = 2% (USDC can vary between 0.98 and 1.02)

uint256 public usdcToleranceBps

devModeEnabled

Dev mode flag to disable spread deviation checks

When enabled, price deviation checks are skipped (dev/testing only)

bool public devModeEnabled

pendingDevMode

Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

Timestamp at which pendingDevMode may be applied (0 = no pending proposal)

uint256 public devModePendingAt

Functions

version

Returns the semantic version of this implementation.

Pure getter (no storage slot) read through the proxy, so it reflects the deployed implementation. Bump per semver on any change; enforced by make check-version-bump. See deployments/{chainId}/versions.json for the deployed impl/commit provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

function version() external pure virtual override returns (string memory);

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

constructor

Constructor for StorkOracle contract

Initializes the TimeProvider and disables initializers for proxy pattern

Notes:

  • security: Validates TimeProvider address is not zero

  • validation: Validates _TIME_PROVIDER is not address(0)

  • state-changes: Sets TIME_PROVIDER immutable variable and disables initializers

  • events: No events emitted

  • errors: Throws "Zero address" if _TIME_PROVIDER is address(0)

  • reentrancy: Not applicable - constructor

  • access: Public - anyone can deploy

  • oracle: No oracle dependencies

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the TimeProvider contract for centralized time management

initialize

Initializes the oracle contract with Stork price feeds

Sets up all core dependencies, roles, and default configuration parameters

Notes:

  • security: Validates all addresses are not zero, grants admin roles

  • validation: Validates all input addresses are not address(0)

  • state-changes: Initializes all state variables, sets default price bounds

  • events: Emits PriceUpdated during initial price update

  • errors: Throws "Oracle: Admin cannot be zero" if admin is address(0)

  • reentrancy: Protected by initializer modifier

  • access: Public - only callable once during deployment

  • oracle: Initializes Stork price feed interfaces

function initialize(
    address admin,
    address _storkFeedAddress,
    bytes32 _eurUsdFeedId,
    bytes32 _usdcUsdFeedId,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_storkFeedAddressaddressStork feed contract address on Base (single contract for all feeds)
_eurUsdFeedIdbytes32Stork EUR/USD feed ID (bytes32)
_usdcUsdFeedIdbytes32Stork USDC/USD feed ID (bytes32)
_treasuryaddressTreasury address for ETH recovery

updateTreasury

Update treasury address

SECURITY: Only admin can update treasury address

Notes:

  • security: Validates treasury address is non-zero

  • validation: Validates _treasury is not address(0)

  • state-changes: Updates treasury state variable

  • events: Emits TreasuryUpdated event

  • errors: Throws if treasury is zero address

  • reentrancy: Not protected - no external calls

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function updateTreasury(address _treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

unpause

Removes pause and resumes oracle operations

Allows emergency role to unpause the oracle after resolving issues

Notes:

  • security: Resumes oracle operations after emergency pause

  • validation: Validates contract was previously paused

  • state-changes: Sets paused state to false

  • events: Emits Unpaused event

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Resumes normal oracle price queries

function unpause() external onlyRole(EMERGENCY_ROLE);

_divRound

Performs division with proper rounding to nearest integer

Adds half the divisor before division to achieve proper rounding

Notes:

  • security: Validates denominator is non-zero

  • validation: Validates b > 0 to prevent division by zero

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws if denominator is zero

  • reentrancy: Not protected - pure function

  • access: Internal - only callable within contract

  • oracle: No oracle dependency

function _divRound(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256Numerator
buint256Denominator

Returns

NameTypeDescription
<none>uint256Result of division with rounding to nearest

_validateTimestamp

Validates if a timestamp is recent enough to prevent manipulation attacks

Checks timestamp is not in future and not too old beyond staleness + drift limits

Notes:

  • security: Prevents timestamp manipulation attacks by miners

  • validation: Checks timestamp is not in future and within staleness limits

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns false for invalid timestamps

  • reentrancy: Not protected - view function

  • access: Internal - only callable within contract

  • oracle: Uses TimeProvider for current time validation

function _validateTimestamp(uint256 reportedTime) internal view returns (bool);

Parameters

NameTypeDescription
reportedTimeuint256The timestamp to validate

Returns

NameTypeDescription
<none>booltrue if the timestamp is valid, false otherwise

_validateEurUsdPriceData

Validates a raw EUR/USD Stork value against freshness, bounds, and deviation policy.

Checks freshness via _validateTimestamp, scales by STORK_FEED_DECIMALS, enforces the [minEurUsdPrice, maxEurUsdPrice] band, and (unless devModeEnabled) rejects a price deviating more than MAX_PRICE_DEVIATION bps from lastValidEurUsdPrice.

Notes:

  • security: Enforces staleness, circuit-breaker bounds, and deviation limits before acceptance.

  • validation: Returns isValid=false on stale, non-positive, out-of-bounds, or over-deviation input.

  • state-changes: None - view function.

  • events: None.

  • errors: None - signals failure via the (0, false) return.

  • reentrancy: Not applicable - view function.

  • access: Internal - no access restrictions.

  • oracle: Reads cached bounds/baseline; does not call the Stork feed.

function _validateEurUsdPriceData(int256 rawPrice, uint256 timestamp)
    internal
    view
    returns (uint256 price, bool isValid);

Parameters

NameTypeDescription
rawPriceint256Raw EUR/USD price from Stork.
timestampuint256Stork update timestamp.

Returns

NameTypeDescription
priceuint256Scaled EUR/USD price, or 0 if validation fails before scaling.
isValidboolTrue when the price can be accepted as the next oracle baseline.

_normalizeUsdcUsdPrice

Normalizes USDC/USD for PriceUpdated events, falling back to $1.00 if invalid.

Returns $1.00 (1e18) unless the Stork value is fresh, positive, and within usdcToleranceBps of $1.00, in which case the value scaled by STORK_FEED_DECIMALS is returned.

Notes:

  • security: Bounds USDC to a tolerance band so a depegged/stale USDC feed cannot distort events.

  • validation: Falls back to 1e18 on stale, non-positive, or out-of-tolerance input.

  • state-changes: None - view function.

  • events: None.

  • errors: None - falls back to 1e18.

  • reentrancy: Not applicable - view function.

  • access: Internal - no access restrictions.

  • oracle: Used only to enrich PriceUpdated events; does not gate EUR/USD reads.

function _normalizeUsdcUsdPrice(int256 rawPrice, uint256 timestamp) internal view returns (uint256 usdcUsdPrice);

Parameters

NameTypeDescription
rawPriceint256Raw USDC/USD price from Stork.
timestampuint256Stork update timestamp.

Returns

NameTypeDescription
usdcUsdPriceuint256Normalized USDC/USD price (18 decimals); $1.00 on any failure.

_readUsdcUsdPriceForEvent

Reads USDC/USD for update events without making EUR/USD reads depend on USDC health.

try/catch reads usdcUsdPriceFeed.getTemporalNumericValueV1(usdcUsdFeedId); returns $1.00 if the call reverts, otherwise delegates to _normalizeUsdcUsdPrice. Decoupled so a failing USDC feed can never block an EUR/USD read.

Notes:

  • security: Isolates USDC-feed failures from the EUR/USD path via try/catch.

  • validation: Delegates range/tolerance checks to _normalizeUsdcUsdPrice.

  • state-changes: None - view function.

  • events: None.

  • errors: None - all failures fall back to 1e18.

  • reentrancy: Not applicable - view function (external staticcall only).

  • access: Internal - no access restrictions.

  • oracle: Reads the USDC/USD Stork feed; result used only for events.

function _readUsdcUsdPriceForEvent() internal view returns (uint256 usdcUsdPrice);

Returns

NameTypeDescription
usdcUsdPriceuint256USDC/USD price (18 decimals) for event enrichment; $1.00 on any failure.

_commitEurUsdPrice

Commits an accepted EUR/USD price as the new oracle deviation baseline.

Stores the accepted EUR/USD price as the new baseline, records update time/block, and emits PriceUpdated. Called only after a value passes _validateEurUsdPriceData.

Notes:

  • security: Reached only after validation; advances the deviation baseline used by later reads.

  • validation: Assumes the caller validated the price; performs no checks itself.

  • state-changes: Sets lastValidEurUsdPrice, lastPriceUpdateTime, lastPriceUpdateBlock.

  • events: Emits PriceUpdated(eurUsdPrice, usdcUsdPrice, timestamp).

  • errors: None.

  • reentrancy: Not applicable - no external calls.

  • access: Internal - no access restrictions.

  • oracle: Updates the cached oracle baseline; does not call the Stork feed.

function _commitEurUsdPrice(uint256 eurUsdPrice, uint256 usdcUsdPrice) internal;

Parameters

NameTypeDescription
eurUsdPriceuint256Accepted EUR/USD price to store as the new baseline (18 decimals).
usdcUsdPriceuint256USDC/USD price included in the emitted event (18 decimals).

_updatePrices

Updates and validates internal prices

Internal function called during initialization and resets, fetches fresh prices from Stork

Notes:

  • security: Validates prices, checks bounds, and triggers circuit breaker if needed

  • validation: Validates timestamp freshness, price bounds, and deviation limits

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateTime, and circuitBreakerTriggered

  • events: Emits PriceUpdated or CircuitBreakerTriggered events

  • errors: No errors thrown, uses circuit breaker for invalid prices

  • reentrancy: Not protected - internal function

  • access: Internal - only callable within contract

  • oracle: Fetches prices from Stork feed contracts for EUR/USD and USDC/USD

function _updatePrices() internal;

_scalePrice

Scale price to 18 decimals for consistency

Converts Stork price from its native decimals to 18 decimals with proper rounding

Notes:

  • security: Handles negative prices by returning 0

  • validation: Validates rawPrice is positive before scaling

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: No errors thrown, returns 0 for negative prices

  • reentrancy: Not protected - pure function

  • access: Internal - only callable within contract

  • oracle: Scales Stork price data to 18 decimals standard

function _scalePrice(int256 rawPrice, uint8 decimals) internal pure returns (uint256);

Parameters

NameTypeDescription
rawPriceint256Raw price from Stork
decimalsuint8Number of decimals in raw price

Returns

NameTypeDescription
<none>uint256Scaled price with 18 decimals

getOracleHealth

Retrieves the oracle global health status

Checks freshness of both price feeds and overall system health

Notes:

  • security: Provides health status for monitoring and circuit breaker decisions

  • validation: Checks feed freshness, circuit breaker state, and pause status

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns false for unhealthy feeds

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Queries Stork feed contracts for EUR/USD and USDC/USD health status

function getOracleHealth() external view returns (bool isHealthy, bool eurUsdFresh, bool usdcUsdFresh);

Returns

NameTypeDescription
isHealthybooltrue if everything operates normally
eurUsdFreshbooltrue if EUR/USD price is fresh
usdcUsdFreshbooltrue if USDC/USD price is fresh

getEurUsdDetails

Retrieves detailed information about the EUR/USD price

Provides comprehensive EUR/USD price information including validation status

Notes:

  • security: Provides detailed price information for debugging and monitoring

  • validation: Checks price freshness and bounds validation

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Queries Stork feed contract for detailed EUR/USD price information

function getEurUsdDetails()
    external
    view
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Timestamp reported by the underlying EUR/USD feed
isStaleboolTrue if the feed data is stale
withinBoundsboolTrue if within configured min/max bounds

getOracleConfig

Retrieves current configuration parameters

Returns all key configuration values for oracle operations

Notes:

  • security: Returns configuration for security monitoring

  • validation: No validation - read-only configuration

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Returns configuration parameters for Stork oracle

function getOracleConfig()
    external
    view
    returns (
        uint256 minPrice,
        uint256 maxPrice,
        uint256 maxStaleness,
        uint256 usdcTolerance,
        bool circuitBreakerActive
    );

Returns

NameTypeDescription
minPriceuint256Minimum EUR/USD price
maxPriceuint256Maximum EUR/USD price
maxStalenessuint256Maximum duration before staleness
usdcToleranceuint256USDC tolerance in basis points
circuitBreakerActiveboolCircuit breaker status

getPriceFeedAddresses

Retrieves addresses of the Stork price feeds used

Returns feed addresses and their decimal configurations

Notes:

  • security: Returns feed addresses for verification

  • validation: No validation - read-only information

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Returns Stork feed contract addresses and decimals (18 for both)

function getPriceFeedAddresses()
    external
    view
    returns (address eurUsdFeedAddress, address usdcUsdFeedAddress, uint8 eurUsdDecimals, uint8 usdcUsdDecimals);

Returns

NameTypeDescription
eurUsdFeedAddressaddressEUR/USD feed address
usdcUsdFeedAddressaddressUSDC/USD feed address
eurUsdDecimalsuint8Number of decimals for the EUR/USD feed
usdcUsdDecimalsuint8Number of decimals for the USDC/USD feed

checkPriceFeedConnectivity

Tests connectivity to the Stork price feeds

Tests if both price feeds are responding and returns latest round information

Notes:

  • security: Tests feed connectivity for health monitoring

  • validation: No validation - connectivity test only

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns false for disconnected feeds

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Tests connectivity to Stork feed contracts for both feeds

function checkPriceFeedConnectivity()
    external
    view
    returns (bool eurUsdConnected, bool usdcUsdConnected, uint80 eurUsdLatestRound, uint80 usdcUsdLatestRound);

Returns

NameTypeDescription
eurUsdConnectedbooltrue if the EUR/USD feed responds
usdcUsdConnectedbooltrue if the USDC/USD feed responds
eurUsdLatestRounduint80Latest round ID for EUR/USD (always 0 for Stork)
usdcUsdLatestRounduint80Latest round ID for USDC/USD (always 0 for Stork)

_authorizeUpgrade

Authorizes oracle contract upgrades

function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation

recoverToken

Recovers tokens accidentally sent to the contract to treasury only

Emergency function to recover ERC20 tokens that are not part of normal operations

Notes:

  • security: Transfers tokens to treasury, prevents accidental loss

  • validation: Validates token and amount are non-zero

  • state-changes: Transfers tokens from contract to treasury

  • events: Emits TokenRecovered event (via library)

  • errors: Throws if token is zero address or transfer fails

  • reentrancy: Protected by library reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverToken(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenaddressAddress of the token to recover
amountuint256Amount to recover

recoverETH

Recover ETH to treasury address only

SECURITY: Restricted to treasury to prevent arbitrary ETH transfers

Notes:

  • security: Transfers ETH to treasury, prevents accidental loss

  • validation: Validates contract has ETH balance

  • state-changes: Transfers ETH from contract to treasury

  • events: Emits ETHRecovered event

  • errors: Throws if transfer fails

  • reentrancy: Protected by library reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependency

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

resetCircuitBreaker

Resets the circuit breaker and resumes oracle usage

Emergency action after resolving an incident. Restarts price updates and disables fallback mode.

Notes:

  • security: Resets circuit breaker after manual intervention

  • validation: Validates circuit breaker was previously triggered

  • state-changes: Resets circuitBreakerTriggered flag and updates prices

  • events: Emits CircuitBreakerReset event

  • errors: No errors thrown

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Resumes normal Stork oracle price queries

function resetCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

triggerCircuitBreaker

Manually triggers the circuit breaker

Used when the team detects an issue with the oracles. Forces the use of the last known valid price.

Notes:

  • security: Manually activates circuit breaker for emergency situations

  • validation: No validation - emergency function

  • state-changes: Sets circuitBreakerTriggered flag to true

  • events: Emits CircuitBreakerTriggered event

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Switches to fallback prices instead of live Stork oracle queries

function triggerCircuitBreaker() external onlyRole(EMERGENCY_ROLE);

pause

Pauses all oracle operations

Emergency function to pause oracle in case of critical issues

Notes:

  • security: Emergency pause to halt all oracle operations

  • validation: No validation - emergency function

  • state-changes: Sets paused state to true

  • events: Emits Paused event

  • errors: No errors thrown

  • reentrancy: Not protected - no external calls

  • access: Restricted to EMERGENCY_ROLE

  • oracle: Halts all Stork oracle price queries

function pause() external onlyRole(EMERGENCY_ROLE);

getEurUsdPrice

Retrieves the current EUR/USD price with full validation

Validation process:

  1. Check circuit breaker status
  2. Fetch from Stork
  3. Freshness check (< 1 hour)
  4. Convert to 18 decimals
  5. Check min/max bounds
  6. Return valid price or fallback

SECURITY NOTE: Stork is a pull oracle — on-chain prices are updated by keeper transactions. An attacker monitoring the off-chain Stork stream can front-run a pending price update by opening a HedgerPool position at the stale price before the update lands. Existing mitigations: (1) MAX_PRICE_DEVIATION circuit breaker caps the per-update magnitude; (2) minPositionHoldBlocks in HedgerPool enforces a minimum hold period after entry. For stronger guarantees, consider a commit-reveal entry scheme or using Stork's push model.

Notes:

  • security: Validates price freshness and bounds before returning

  • validation: Checks price staleness, circuit breaker state, and bounds

  • state-changes: Updates lastValidEurUsdPrice, lastPriceUpdateTime, and lastPriceUpdateBlock when valid

  • events: Emits PriceUpdated when a valid price advances the baseline

  • errors: No errors thrown, returns isValid=false for invalid prices

  • reentrancy: Not protected - external oracle read only

  • access: Public - no access restrictions

  • oracle: Queries Stork feed contract for EUR/USD price

function getEurUsdPrice() external returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals (e.g., 1.10e18 = 1.10 USD per EUR)
isValidbooltrue if the price is fresh and within acceptable bounds

getUsdcUsdPrice

Retrieves the USDC/USD price with validation

USDC is expected to maintain parity with USD. A large deviation indicates a systemic issue.

Notes:

  • security: Validates price is within tolerance of $1.00

  • validation: Checks price staleness and deviation from $1.00

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown, returns isValid=false for invalid prices

  • reentrancy: Not protected - view function

  • access: Public - no access restrictions

  • oracle: Queries Stork feed contract for USDC/USD price

function getUsdcUsdPrice() external view returns (uint256 price, bool isValid);

Returns

NameTypeDescription
priceuint256USDC/USD price in 18 decimals (should be close to 1.0e18)
isValidbooltrue if USDC remains close to $1.00

updatePriceBounds

Updates price bounds for the circuit breaker

Allows oracle manager to adjust price thresholds based on market conditions

Notes:

  • security: Validates min < max and reasonable bounds

  • validation: Validates price bounds are within acceptable range

  • state-changes: Updates minEurUsdPrice and maxEurUsdPrice state variables

  • events: Emits PriceBoundsUpdated event

  • errors: Throws if minPrice >= maxPrice or invalid bounds

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency - configuration update only

function updatePriceBounds(uint256 _minPrice, uint256 _maxPrice) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_minPriceuint256Minimum accepted EUR/USD price (18 decimals)
_maxPriceuint256Maximum accepted EUR/USD price (18 decimals)

updateUsdcTolerance

Updates the tolerance for USDC/USD

Allows oracle manager to adjust USDC price tolerance around $1.00

Notes:

  • security: Validates tolerance is within reasonable limits

  • validation: Validates tolerance is not zero and within max bounds (10%)

  • state-changes: Updates usdcToleranceBps state variable

  • events: No events emitted

  • errors: Throws if tolerance is invalid or out of bounds

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: No oracle dependency - configuration update only

function updateUsdcTolerance(uint256 newToleranceBps) external onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
newToleranceBpsuint256New tolerance in basis points (e.g., 200 = 2%)

updatePriceFeeds

Updates the Stork feed address and feed IDs

Allows oracle manager to update feed address and feed IDs for maintenance or upgrades Note: Stork uses a single contract address with different feed IDs

Notes:

  • security: Validates feed address is non-zero and contract exists

  • validation: Validates all addresses are not address(0)

  • state-changes: Updates eurUsdPriceFeed, usdcUsdPriceFeed, and feed IDs

  • events: Emits PriceFeedsUpdated event

  • errors: Throws if feed address is zero or invalid

  • reentrancy: Not protected by a reentrancy guard

  • access: Restricted to ORACLE_MANAGER_ROLE

  • oracle: Updates Stork feed contract references

function updatePriceFeeds(address _storkFeedAddress, bytes32 _eurUsdFeedId, bytes32 _usdcUsdFeedId)
    external
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_storkFeedAddressaddressNew Stork feed contract address
_eurUsdFeedIdbytes32New EUR/USD feed ID
_usdcUsdFeedIdbytes32New USDC/USD feed ID

proposeDevMode

Toggles dev mode to disable spread deviation checks

Propose a dev-mode change; enforces a 48-hour timelock before it can be applied.

DEV ONLY: When enabled, price deviation checks are skipped for testing

Records a desired value for devModeEnabled in pendingDevMode and sets devModePendingAt to block.timestamp + DEV_MODE_DELAY. This does not affect current deviation checks until applyDevMode is executed after the delay.

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE; separates intent from effect to avoid rushed enabling/disabling of deviation checks.

  • validation: Accepts both true and false; applies a fixed delay in all cases.

  • state-changes: Updates pendingDevMode and devModePendingAt.

  • events: Emits DevModeProposed(enabled, devModePendingAt).

  • errors: None – proposals are always recorded.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No direct oracle dependency; controls deviation checks in price paths.

function proposeDevMode(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolTrue to enable dev mode, false to disable

applyDevMode

Apply a previously proposed dev-mode change after the timelock has elapsed.

Checks that devModePendingAt is non-zero and that the current block timestamp has reached or passed devModePendingAt. If so, copies pendingDevMode into devModeEnabled and clears devModePendingAt.

Notes:

  • security: Only callable by DEFAULT_ADMIN_ROLE; enforces the configured delay.

  • validation: Reverts when there is no pending proposal or the delay window is not met.

  • state-changes: Updates devModeEnabled and resets devModePendingAt to 0.

  • events: Emits DevModeToggled(devModeEnabled, msg.sender).

  • errors: InvalidAmount if no pending proposal; NotActive if called before delay elapses.

  • reentrancy: Not applicable – no external calls after state updates.

  • access: Restricted to DEFAULT_ADMIN_ROLE.

  • oracle: No direct oracle dependency; influences later deviation checks.

function applyDevMode() external onlyRole(DEFAULT_ADMIN_ROLE);

Events

PriceUpdated

Emitted on each valid price update

OPTIMIZED: Indexed timestamp for efficient time-based filtering

event PriceUpdated(uint256 eurUsdPrice, uint256 usdcUsdPrice, uint256 indexed timestamp);

CircuitBreakerTriggered

Emitted when the circuit breaker is triggered

OPTIMIZED: Indexed reason for efficient filtering by trigger type

event CircuitBreakerTriggered(uint256 attemptedPrice, uint256 lastValidPrice, string indexed reason);

CircuitBreakerReset

Emitted when the circuit breaker is reset

event CircuitBreakerReset(address indexed admin);

PriceBoundsUpdated

Emitted when price bounds are modified

OPTIMIZED: Indexed bound type for efficient filtering

event PriceBoundsUpdated(string indexed boundType, uint256 newMinPrice, uint256 newMaxPrice);

PriceFeedsUpdated

Emitted when price feed addresses are updated

event PriceFeedsUpdated(
    address newEurUsdFeed, address newUsdcUsdFeed, bytes32 newEurUsdFeedId, bytes32 newUsdcUsdFeedId
);

TreasuryUpdated

Emitted when treasury address is updated

event TreasuryUpdated(address indexed newTreasury);

Parameters

NameTypeDescription
newTreasuryaddressNew treasury address

ETHRecovered

Emitted when ETH is recovered from the contract

event ETHRecovered(address indexed to, uint256 amount);

DevModeToggled

Emitted when dev mode is toggled

event DevModeToggled(bool enabled, address indexed caller);

Parameters

NameTypeDescription
enabledboolWhether dev mode is enabled or disabled
calleraddressAddress that triggered the toggle

DevModeProposed

Emitted when a dev-mode change is proposed

event DevModeProposed(bool pending, uint256 activatesAt);

Parameters

NameTypeDescription
pendingboolThe proposed dev-mode value
activatesAtuint256Timestamp at which the change can be applied