Quantillon Protocol

Quantillon Protocol Smart Contracts

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 includes 1,300+ tests, 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
  • Advanced Hedging: EUR/USD hedging positions with margin management and liquidation systems
  • Yield-Bearing Wrapper: stQEURO token that automatically accrues yield for holders
  • Aave Integration: Automated yield farming through Aave protocol integration
  • 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, fixed supply (100M), lock periods, 4× voting power
QuantillonVaultMain vaultOvercollateralized minting (≥105%), liquidation at 101%, fee management
FeeCollectorFee distribution60/25/15 split to treasury/dev/community, per-token accounting
UserPoolUser depositsUSDC deposits, QEURO staking, unstaking cooldown, yield distribution
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
AaveVaultAave v3 integrationAutomated USDC yield farming, reward harvesting, emergency controls
YieldShiftYield managementDynamic distribution between pools, 7-day holding period, TWAP-based allocation
OracleRouterOracle routingRoutes between Chainlink and Stork oracles, switchable by governance
ChainlinkOracleChainlink price feedsEUR/USD and USDC/USD via Chainlink, 1 hr staleness check, circuit breakers
StorkOracleStork price feedsEUR/USD and USDC/USD via Stork Network, same validation as Chainlink
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: Some folders (scripts/) are encrypted with git-crypt for privacy concerns. If you need access to these files, you'll need the encryption key. Contact the maintainers for access.

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) runs make build && make test on push and pull requests to main. 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

All 13 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

📋 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: Manage secrets with standard .env files (never commit them)
  • 🌐 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: Use standard .env files (never commit them)
  • 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 Folders: Some folders (e.g., scripts/) are encrypted with git-crypt for privacy and security. These files require the encryption key to decrypt and access.

📊 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 with 1,300+ tests (100% passing)
  • 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; never commit .env
  • 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
  • Aave for yield farming integration
  • Foundry for development framework
  • Standard .env files for environment variable management

Quantillon Protocol API Documentation

Overview

The Quantillon Protocol is a comprehensive DeFi ecosystem built on Base, featuring a euro-pegged stablecoin (QEURO), governance token (QTI), and advanced yield management system. This document provides detailed API documentation for all public interfaces.

Table of Contents

  1. Core Contracts
  2. Vault Contracts
  3. Yield Management
  4. Oracle System
  5. Utilities
  6. Error Codes
  7. Events
  8. Integration Examples

Core Contracts

QuantillonVault

The main vault contract that manages QEURO minting and redemption against USDC.

Functions

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

Initializes the vault with initial configuration.

Parameters:

  • admin (address): Admin address receiving roles
  • _qeuro (address): QEURO token address
  • _usdc (address): USDC token address
  • _oracle (address): Oracle contract address
  • _hedgerPool (address): HedgerPool address (can be set later)
  • _userPool (address): UserPool address (can be set later)
  • _timelock (address): Timelock/treasury address
  • _feeCollector (address): FeeCollector address

Access: Public (only callable once)

mintQEURO(uint256 usdcAmount, uint256 minQeuroOut)

Mints QEURO by swapping USDC.

Parameters:

  • usdcAmount (uint256): Amount of USDC to swap (6 decimals)
  • minQeuroOut (uint256): Minimum QEURO expected (18 decimals, slippage protection)

Access: Public

Requirements:

  • Contract not paused
  • Valid oracle price and initialized price cache (initializePriceCache)
  • Active hedger (hedgerPool.hasActiveHedger())
  • Sufficient USDC balance and allowance
redeemQEURO(uint256 qeuroAmount, uint256 minUsdcOut)

Redeems QEURO for USDC.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO to swap (18 decimals)
  • minUsdcOut (uint256): Minimum USDC expected (6 decimals, slippage protection)

Access: Public

Requirements:

  • Contract not paused
  • Valid oracle price (normal mode)
  • Sufficient QEURO balance and allowance
  • Automatically routes to liquidation redemption when protocol CR is at or below critical threshold
calculateMintAmount(uint256 usdcAmount) → (uint256, uint256)

Calculates quoted mint output using cached price.

Parameters:

  • usdcAmount (uint256): Amount of USDC (6 decimals)

Returns:

  • uint256: Amount of QEURO that would be minted (18 decimals)
  • uint256: Mint fee (USDC, 6 decimals)

Access: Public view

calculateRedeemAmount(uint256 qeuroAmount) → (uint256, uint256)

Calculates quoted redeem output using cached price.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO (18 decimals)

Returns:

  • uint256: Amount of USDC that would be received (6 decimals)
  • uint256: Redemption fee (USDC, 6 decimals)

Access: Public view

getVaultMetrics() → (uint256, uint256, uint256, uint256, uint256)

Retrieves comprehensive vault metrics.

Returns:

  • uint256: totalUsdcHeld (USDC in vault, 6 decimals)
  • uint256: totalMinted (QEURO tracked by vault, 18 decimals)
  • uint256: totalDebtValue (USD value from live supply and cached EUR/USD)
  • uint256: totalUsdcInExternalVaults (tracked principal across external adapters)
  • uint256: totalUsdcAvailable (vault + external vault balances including accrued yield)

Access: Public view

getProtocolCollateralizationRatio() → (uint256)

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

canMint() → (bool)

Returns whether minting is currently allowed.

getProtocolCollateralizationRatioView() → (uint256) / canMintView() → (bool)

View-safe aliases that use cached price path (no state refresh side effects).

initializePriceCache()

Seeds the cached EUR/USD price after deployment (required before first mint).

updateHedgerRewardFeeSplit(uint256 newSplit)

Updates the fee share routed to HedgerPool reserve (1e18 = 100%).

mintQEUROToVault(uint256 usdcAmount, uint256 minQeuroOut, uint256 vaultId)

Mints QEURO and routes collateral to a specific external vault adapter.

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

One-step flow: mint QEURO and immediately stake into stQEURO{vaultName} for the selected vaultId.

harvestVaultYield(uint256 vaultId) → (uint256)

Triggers yield harvest for a specific external vault adapter.

deployUsdcToVault(uint256 vaultId, uint256 usdcAmount)

Operator function to manually deploy vault-held USDC into a selected external vault adapter.

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 ExternalVaultYieldHarvested(uint256 indexed vaultId, uint256 harvestedYield);

QEUROToken

The euro-pegged stablecoin token with compliance features.

Functions

mint(address to, uint256 amount)

Mints QEURO tokens to a specified address.

Parameters:

  • to (address): Recipient address
  • amount (uint256): Amount to mint (18 decimals)

Access: Vault role only

burn(uint256 amount)

Burns QEURO tokens from the caller's balance.

Parameters:

  • amount (uint256): Amount to burn (18 decimals)

Access: Vault role only

whitelistAddress(address account)

Adds an address to the whitelist.

Parameters:

  • account (address): Address to whitelist

Access: Compliance role only

blacklistAddress(address account)

Adds an address to the blacklist.

Parameters:

  • account (address): Address to blacklist

Access: Compliance role only

updateMaxSupply(uint256 newMaxSupply)

Updates the maximum supply cap.

Parameters:

  • newMaxSupply (uint256): New maximum supply (18 decimals)

Access: Admin role only

getTokenInfo() → (uint256, uint256, uint256, bool, bool)

Retrieves comprehensive token information.

Returns:

  • uint256: Total supply
  • uint256: Maximum supply
  • uint256: Supply utilization percentage
  • bool: Whitelist mode enabled
  • bool: Contract paused

Access: Public view

Events

event TokensMinted(address indexed to, uint256 amount);
event TokensBurned(address indexed from, uint256 amount);
event AddressWhitelisted(address indexed account);
event AddressBlacklisted(address indexed account);
event MaxSupplyUpdated(uint256 oldMaxSupply, uint256 newMaxSupply);

QTIToken

The governance token with vote-escrow mechanics.

Functions

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

Locks QTI tokens for voting power.

Parameters:

  • amount (uint256): Amount of QTI to lock (18 decimals)
  • lockTime (uint256): Duration to lock (seconds)

Returns:

  • uint256: Voting power received (18 decimals)

Access: Public

Requirements:

  • Sufficient QTI balance
  • Lock time between minimum and maximum duration
unlock() → (uint256)

Unlocks QTI tokens after lock period expires.

Returns:

  • uint256: Amount of QTI unlocked

Access: Public

Requirements:

  • Lock period has expired
getVotingPower(address user) → (uint256)

Gets current voting power for an address.

Parameters:

  • user (address): User address

Returns:

  • uint256: Current voting power (18 decimals)

Access: Public view

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

Gets lock information for an address.

Parameters:

  • user (address): User address

Returns:

  • uint256: Locked amount
  • uint256: Lock time
  • uint256: Unlock time
  • uint256: Current voting power

Access: Public view

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

Creates a new governance proposal.

Parameters:

  • description (string): Proposal description
  • startTime (uint256): Voting start time
  • endTime (uint256): Voting end time

Returns:

  • uint256: Proposal ID

Access: Public

Requirements:

  • Sufficient voting power
  • Valid time parameters
vote(uint256 proposalId, bool support)

Votes on a governance proposal.

Parameters:

  • proposalId (uint256): Proposal ID
  • support (bool): True for yes, false for no

Access: Public

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

Manages user deposits, staking, and yield distribution.

Functions

deposit(uint256 usdcAmount)

Deposits USDC into the user pool.

Parameters:

  • usdcAmount (uint256): Amount of USDC to deposit (6 decimals)

Access: Public

Requirements:

  • Contract not paused
  • Sufficient USDC balance and allowance
withdraw(uint256 usdcAmount)

Withdraws USDC from the user pool.

Parameters:

  • usdcAmount (uint256): Amount of USDC to withdraw (6 decimals)

Access: Public

Requirements:

  • Sufficient balance
  • Contract not paused
stake(uint256 qeuroAmount)

Stakes QEURO tokens for rewards.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO to stake (18 decimals)

Access: Public

Requirements:

  • Sufficient QEURO balance and allowance
  • Above minimum stake amount
unstake(uint256 qeuroAmount)

Unstakes QEURO tokens.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO to unstake (18 decimals)

Access: Public

Requirements:

  • Sufficient staked balance
  • Cooldown period completed
claimStakingRewards() → (uint256)

Claims accumulated staking rewards.

Returns:

  • uint256: Amount of rewards claimed

Access: Public

getUserInfo(address user) → (uint256, uint256, uint256, uint256, uint256)

Gets comprehensive user information.

Parameters:

  • user (address): User address

Returns:

  • uint256: Deposited USDC amount
  • uint256: Staked QEURO amount
  • uint256: Last stake time
  • uint256: Pending rewards
  • uint256: Total rewards claimed

Access: Public view

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

Gets pool metrics.

Returns:

  • uint256: Total users
  • uint256: Total stakes
  • uint256: Total deposits
  • uint256: Total rewards distributed

Access: Public view

Events

event USDCDeposited(address indexed user, uint256 amount);
event USDCWithdrawn(address indexed user, uint256 amount);
event QEUROStaked(address indexed user, uint256 amount);
event QEUROUnstaked(address indexed user, uint256 amount);
event RewardsClaimed(address indexed user, uint256 amount);

HedgerPool

Manages the protocol’s single-hedger leveraged position and hedger reward settlement.

Functions

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

Opens a new hedge position.

Parameters:

  • usdcAmount (uint256): USDC margin amount (6 decimals)
  • leverage (uint256): Leverage multiplier (1-10x)

Returns:

  • uint256: Position ID

Access: Public

Requirements:

  • Caller must be the configured singleHedger
  • Valid leverage amount
  • Sufficient USDC balance and allowance
  • Fresh oracle price
exitHedgePosition(uint256 positionId) → (int256)

Closes the active hedge position.

Parameters:

  • positionId (uint256): Position ID to close

Returns:

  • int256: Profit or loss (positive = profit, negative = loss)

Access: Public

Requirements:

  • Position exists and is active
  • Caller owns the position
addMargin(uint256 positionId, uint256 usdcAmount)

Adds margin to an existing position.

Parameters:

  • positionId (uint256): Position ID
  • usdcAmount (uint256): Additional USDC margin (6 decimals)

Access: Public

Requirements:

  • Position exists and is active
  • Caller owns the position
removeMargin(uint256 positionId, uint256 usdcAmount)

Removes margin from a position.

Parameters:

  • positionId (uint256): Position ID
  • usdcAmount (uint256): USDC amount to remove (6 decimals)

Access: Public

Requirements:

  • Position exists and is active
  • Caller owns the position
  • Maintains minimum margin ratio
claimHedgingRewards() → (uint256, uint256, uint256)

Claims hedger rewards.

Returns:

  • uint256: Interest differential paid/escrowed by HedgerPool reserve
  • uint256: YieldShift rewards claimed via YieldShift
  • uint256: Total rewards for reporting (interest + yieldShift)

Access: Restricted to configured singleHedger

withdrawPendingRewards(address recipient)

Withdraws reward amounts escrowed after failed push-transfer in claimHedgingRewards.

hasActiveHedger() → (bool)

Returns whether a configured single hedger currently has an active position.

setSingleHedger(address hedger)

Bootstrap/rotation entrypoint for single hedger configuration (governance-only).
If no hedger is configured yet, assignment is immediate. Otherwise it creates a delayed pending rotation.

applySingleHedgerRotation()

Applies a previously proposed single-hedger rotation after delay (governance-only).

fundRewardReserve(uint256 amount)

Permissionless reserve top-up path for hedger rewards.

configureRiskAndFees((...))

Batch governance update for:

  • margin ratio / leverage limits
  • hold blocks / minimum margin
  • EUR/USD interest rates
  • entry / exit / margin fees
  • rewardFeeSplit (1e18 = 100%)
configureDependencies((...))

Batch governance update for:

  • treasury
  • vault
  • oracle
  • yieldShift
  • feeCollector

Events

event HedgePositionOpened(address indexed hedger, uint256 indexed positionId, bytes32 positionData);
event HedgePositionClosed(address indexed hedger, uint256 indexed positionId, bytes32 packedData);
event MarginUpdated(address indexed hedger, uint256 indexed positionId, bytes32 packedData);
event HedgingRewardsClaimed(address indexed hedger, bytes32 packedData);
event HedgerFillUpdated(uint256 indexed positionId, uint256 previousFilled, uint256 newFilled);
event RewardReserveFunded(address indexed funder, uint256 amount);
event SingleHedgerRotationProposed(address indexed currentHedger, address indexed pendingHedger, uint256 activatesAt);
event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

stQEUROFactory

Factory contract for vault-scoped staking tokens.

Functions

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

Registers the calling vault and deploys a dedicated stQEURO token proxy.

Parameters:

  • vaultId (uint256): Non-zero vault id
  • vaultName (string): Uppercase alphanumeric vault suffix (length 1..12)

Returns:

  • address: Newly deployed stQEURO token for the vault

Access: VAULT_FACTORY_ROLE only, strict self-registration semantics (msg.sender is the vault)

getStQEUROByVaultId(uint256 vaultId) -> (address)

Resolves stQEURO token address for a given vault id.

getStQEUROByVault(address vault) -> (address)

Resolves stQEURO token address for a given vault address.

getVaultById(uint256 vaultId) -> (address)

Returns vault address for a registered vault id.

getVaultIdByStQEURO(address stQEUROToken) -> (uint256)

Returns vault id mapped to an stQEURO token address.

getVaultName(uint256 vaultId) -> (string)

Returns vault name suffix stored at registration.

updateYieldShift(address newYieldShift)

Governance setter for YieldShift dependency used for newly deployed stQEURO tokens.

updateTokenImplementation(address newImplementation)

Governance setter for stQEURO token implementation address used by future proxies.

updateTreasury(address newTreasury) / updateTokenAdmin(address newAdmin) / updateOracle(address newOracle)

Governance setters for factory-level defaults used during vault token deployment.

Events

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

stQEUROToken

Staked QEURO token with yield distribution.

Functions

stake(uint256 qeuroAmount)

Stakes QEURO tokens to receive stQEURO.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO to stake (18 decimals)

Access: Public

Requirements:

  • Sufficient QEURO balance and allowance
unstake(uint256 stQeuroAmount)

Unstakes stQEURO tokens to receive QEURO.

Parameters:

  • stQeuroAmount (uint256): Amount of stQEURO to unstake (18 decimals)

Access: Public

Requirements:

  • Sufficient stQEURO balance
claimYield() → (uint256)

Claims accumulated yield.

Returns:

  • uint256: Amount of yield claimed

Access: Public

getExchangeRate() → (uint256)

Gets current exchange rate between stQEURO and QEURO.

Returns:

  • uint256: Exchange rate (18 decimals)

Access: Public view

getQEUROEquivalent(uint256 stQeuroAmount) → (uint256)

Calculates QEURO equivalent for stQEURO amount.

Parameters:

  • stQeuroAmount (uint256): Amount of stQEURO (18 decimals)

Returns:

  • uint256: Equivalent QEURO amount (18 decimals)

Access: Public view

distributeYield(uint256 qeuroAmount)

Distributes yield to stakers.

Parameters:

  • qeuroAmount (uint256): Amount of QEURO to distribute (18 decimals)

Access: Yield manager role only

initialize(...) (dynamic metadata overload)

Supports per-vault metadata (tokenName, tokenSymbol, vaultName) when deployed through stQEUROFactory.

Events

event QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 stQeuroAmount);
event QEUROUnstaked(address indexed user, uint256 stQeuroAmount, uint256 qeuroAmount);
event YieldClaimed(address indexed user, uint256 amount);
event YieldDistributed(uint256 totalAmount, uint256 timestamp);


Fee Management

FeeCollector

Centralized protocol fee collection and distribution.

Functions

collectFee(address token, uint256 amount)

Records a collected fee from a protocol contract.

Parameters:

  • token (address): Token address (e.g. USDC)
  • amount (uint256): Fee amount collected

Access: Authorized protocol contracts only

distributeFees(address token)

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

Parameters:

  • token (address): Token to distribute

Access: GOVERNANCE_ROLE

updateFeeRatios(uint256 treasury, uint256 dev, uint256 community)

Updates fee distribution ratios.

Parameters:

  • treasury (uint256): Treasury ratio (basis points, default 6000 = 60%)
  • dev (uint256): Dev fund ratio (basis points, default 2500 = 25%)
  • community (uint256): Community fund ratio (basis points, default 1500 = 15%)

Access: GOVERNANCE_ROLE

Requirements:

  • treasury + dev + community == 10000
withdrawFees(address token)

Withdraws collected fees to the caller's role-permitted address.

Access: TREASURY_ROLE

Events

event FeeCollected(address indexed token, uint256 amount);
event FeesDistributed(address indexed token, uint256 treasury, uint256 dev, uint256 community);
event FeeRatiosUpdated(uint256 treasury, uint256 dev, uint256 community);

Vault Contracts

AaveVault

Manages yield generation through Aave v3 protocol integration.

Functions

deployToAave(uint256 usdcAmount)

Deploys USDC to Aave for yield generation.

Parameters:

  • usdcAmount (uint256): Amount of USDC to deploy (6 decimals)

Access: Yield manager role only

Requirements:

  • Sufficient USDC balance
  • Within exposure limits
withdrawFromAave(uint256 usdcAmount)

Withdraws USDC from Aave.

Parameters:

  • usdcAmount (uint256): Amount of USDC to withdraw (6 decimals)

Access: Yield manager role only

harvestAaveYield() → (uint256)

Harvests accumulated yield from Aave.

Returns:

  • uint256: Amount of yield harvested

Access: Yield manager role only

Notes:

  • Reverts if yieldVaultId is not configured (yieldVaultId == 0)
  • Routes harvested yield to YieldShift.addYield(yieldVaultId, ...)
setYieldVaultId(uint256 newYieldVaultId)

Sets the destination vault id used when routing harvested Aave yield to YieldShift.

Access: Governance role only

updateYieldShift(address newYieldShift)

Updates the YieldShift dependency used by AaveVault for yield routing.

Access: Governance role only

getAaveBalance() → (uint256)

Gets current USDC balance in Aave.

Returns:

  • uint256: USDC balance in Aave (6 decimals)

Access: Public view

getAaveAPY() → (uint256)

Gets current Aave APY.

Returns:

  • uint256: APY in basis points

Access: Public view

autoRebalance() → (bool, uint256, uint256)

Automatically rebalances Aave position.

Returns:

  • bool: Whether rebalancing occurred
  • uint256: New allocation percentage
  • uint256: Expected yield

Access: Public

Events

event USDCDepositedToAave(uint256 amount);
event USDCWithdrawnFromAave(uint256 amount);
event AaveYieldHarvested(uint256 amount);
event AavePositionRebalanced(uint256 newAllocation, uint256 expectedYield);

Yield Management

YieldShift

Manages yield distribution between user and hedger pools.

Functions

addYield(uint256 vaultId, uint256 yieldAmount, bytes32 source)

Adds yield to the distribution system.

Parameters:

  • vaultId (uint256): Registered staking vault id receiving user-allocation yield
  • yieldAmount (uint256): Amount of USDC yield to add (6 decimals)
  • source (bytes32): Source key ("aave", "fees", "interest_differential", etc.)

Access: Authorized yield sources only

updateYieldDistribution()

Refreshes and applies current distribution between user and hedger pools.

Access: Public (whenNotPaused)

claimUserYield(address user) → (uint256)

Claims yield for user pool.

Returns:

  • uint256: Amount of yield claimed

Access: YIELD_MANAGER_ROLE

claimHedgerYield(address hedger) → (uint256)

Claims yield for hedger pool.

Returns:

  • uint256: Amount of yield claimed

Access: YIELD_MANAGER_ROLE

configureYieldModel((...))

Batch governance update for:

  • baseYieldShift
  • maxYieldShift
  • adjustmentSpeed
  • targetPoolRatio
configureDependencies((...))

Batch governance update for:

  • userPool
  • hedgerPool
  • aaveVault
  • stQEUROFactory
  • treasury
setYieldSourceAuthorization(address source, bytes32 yieldType, bool authorized)

Adds/removes an authorized yield source with explicit yield type mapping.

currentYieldShift() → (uint256)

Direct state getter for current shift (1e4 precision).

userPendingYield(address user) → (uint256) / hedgerPendingYield(address hedger) → (uint256)

Direct state getters for pending yield balances.

paused() → (bool)

Pausable state getter. Yield distribution is active when paused() == false.

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

Gets pool metrics for yield calculation.

Returns:

  • uint256: User pool size
  • uint256: Hedger pool size
  • uint256: Pool ratio
  • uint256: Target ratio

Access: Public view

calculateOptimalYieldShift() → (uint256, uint256)

Calculates optimal yield distribution.

Returns:

  • uint256: Optimal shift
  • uint256: Current deviation from optimal

Access: Public view

Events

event YieldDistributionUpdated(uint256 userPoolYield, uint256 hedgerPoolYield, uint256 currentShift);
event YieldAdded(uint256 yieldAmount, string indexed source, uint256 indexed timestamp);
event UserYieldClaimed(address indexed user, uint256 yieldAmount, uint256 timestamp);
event HedgerYieldClaimed(address indexed hedger, uint256 yieldAmount, uint256 timestamp);

Oracle System

The oracle system consists of three contracts. All protocol contracts interact only with OracleRouter via the IOracle interface — the underlying oracle source can be switched by governance without any changes to the protocol.

OracleRouter

Routes price requests to the currently active oracle (ChainlinkOracle or StorkOracle).

Functions

getLatestPrice() → (uint256, bool)

Gets the current EUR/USD price from the active oracle.

Returns:

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

Access: Public view

switchOracle(uint8 newOracleType)

Switches the active oracle between Chainlink (0) and Stork (1).

Parameters:

  • newOracleType (uint8): 0 = Chainlink, 1 = Stork

Access: ORACLE_MANAGER_ROLE

Updates the underlying oracle contract addresses.

Parameters:

  • chainlink (address): ChainlinkOracle proxy address
  • stork (address): StorkOracle proxy address

Access: ORACLE_MANAGER_ROLE

Events

event OracleSwitched(uint8 oldOracle, uint8 newOracle, address caller);
event OracleAddressesUpdated(address newChainlink, address newStork);

ChainlinkOracle

EUR/USD and USDC/USD price feeds via Chainlink AggregatorV3.

Validation rules:

  • Max staleness: 3600 seconds (1 hour)
  • Max deviation: 500 basis points (5%)
  • Timestamp drift detection: 900 seconds (15 minutes)

Functions

getLatestPrice() → (uint256, bool)

Gets current EUR/USD price from Chainlink.

Returns:

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

Access: Public view

updatePriceFeeds(address eurUsdFeed, address usdcUsdFeed)

Updates Chainlink price feed addresses.

Parameters:

  • eurUsdFeed (address): EUR/USD Chainlink aggregator address
  • usdcUsdFeed (address): USDC/USD Chainlink aggregator address

Access: ORACLE_MANAGER_ROLE

Events

event PriceFeedsUpdated(address eurUsdFeed, address usdcUsdFeed);
event CircuitBreakerTriggered(uint256 timestamp);
event CircuitBreakerReset(uint256 timestamp);

StorkOracle

EUR/USD and USDC/USD price feeds via Stork Network. Same IOracle interface as ChainlinkOracle.

Validation rules: identical to ChainlinkOracle (staleness, deviation, timestamp drift).

Functions

getLatestPrice() → (uint256, bool)

Gets current EUR/USD price from Stork Network.

Returns:

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

Access: Public view

updateFeedIds(bytes32 eurUsdId, bytes32 usdcUsdId)

Updates Stork feed IDs.

Parameters:

  • eurUsdId (bytes32): EUR/USD Stork feed ID (default: keccak256("EURUSD"))
  • usdcUsdId (bytes32): USDC/USD Stork feed ID (default: keccak256("USDCUSD"))

Access: ORACLE_MANAGER_ROLE

Events

event FeedIdsUpdated(bytes32 eurUsdId, bytes32 usdcUsdId);

Utilities

TimeProvider

Provides time utilities with offset capabilities.

Functions

currentTime() → (uint256)

Gets current time with offset.

Returns:

  • uint256: Current timestamp

Access: Public view

setTimeOffset(int256 offset)

Sets time offset.

Parameters:

  • offset (int256): Time offset in seconds

Access: Time manager role only

advanceTime(uint256 amount)

Advances time by specified amount.

Parameters:

  • amount (uint256): Time to advance in seconds

Access: Time manager role only

isFuture(uint256 timestamp) → (bool)

Checks if timestamp is in the future.

Parameters:

  • timestamp (uint256): Timestamp to check

Returns:

  • bool: True if timestamp is in the future

Access: Public view

Events

event TimeOffsetSet(int256 oldOffset, int256 newOffset);
event TimeAdvanced(uint256 amount);

Error Codes

The protocol uses custom errors for gas efficiency. Common error codes include:

// Access Control
error UnauthorizedAccess();
error InsufficientRole();

// Validation
error InvalidAmount();
error InvalidAddress();
error InvalidParameter();
error InvalidTime();

// Business Logic
error InsufficientBalance();
error InsufficientAllowance();
error ExceedsLimit();
error BelowMinimum();

// Oracle
error StalePrice();
error InvalidPrice();
error CircuitBreakerActive();

// Emergency
error ContractPaused();
error EmergencyMode();

// Liquidation
error PositionHealthy();
error InsufficientMargin();

Events

All contracts emit comprehensive events for state changes. Key event categories:

Core Events

  • Token transfers and approvals
  • Deposits and withdrawals
  • Staking and unstaking
  • Yield distribution

Governance Events

  • Proposal creation and execution
  • Voting and delegation
  • Parameter updates

Risk Management Events

  • Position opening and closing
  • Liquidations
  • Circuit breaker activations

Emergency Events

  • Pause and unpause
  • Emergency withdrawals
  • Recovery operations

Integration Examples

Basic QEURO Minting

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

// 2. Mint QEURO with slippage protection
uint256 minQeuroOut = (usdcAmount * 95) / 100; // 5% slippage tolerance
vault.mintQEURO(usdcAmount, minQeuroOut);

Staking QEURO for Rewards

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

// 2. Stake QEURO
userPool.stake(qeuroAmount);

// 3. Claim rewards later
uint256 rewards = userPool.claimStakingRewards();

Opening a Hedge Position

// 1. Approve USDC spending
usdc.approve(hedgerPoolAddress, marginAmount);

// 2. Open position with 5x leverage
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

// 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 documentation is maintained by Quantillon Labs and updated regularly. Last updated: March 2026

Quantillon Protocol API Reference

Technical API Reference

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


Contract Addresses

Note: These are example addresses for documentation. Use actual deployed addresses in production.

ContractAddressNetwork
QuantillonVault0x...Base Mainnet
QEUROToken0x...Base Mainnet
QTIToken0x...Base Mainnet
UserPool0x...Base Mainnet
HedgerPool0x...Base Mainnet
stQEUROFactory0x...Base Mainnet
stQEUROToken0x...Base Mainnet
AaveVault0x...Base Mainnet
YieldShift0x...Base Mainnet
ChainlinkOracle0x...Base Mainnet

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 at or below critical threshold
  • Pulls liquidity from Aave when needed (including accrued yield)

calculateMintAmount(uint256 usdcAmount) → (uint256, uint256)

function calculateMintAmount(uint256 usdcAmount) external view returns (uint256 qeuroAmount, uint256 fee)

Returns:

  • qeuroAmount: Amount of QEURO that would be minted (18 decimals)
  • fee: Mint fee amount (USDC, 6 decimals)

Notes:

  • Uses cached EUR/USD price path (lastValidEurUsdPrice).

calculateRedeemAmount(uint256 qeuroAmount) → (uint256, uint256)

function calculateRedeemAmount(uint256 qeuroAmount) external view returns (uint256 usdcAmount, uint256 fee)

Returns:

  • usdcAmount: Amount of USDC that would be received (6 decimals)
  • fee: Redemption fee amount (USDC, 6 decimals)

Notes:

  • Uses cached EUR/USD price path (lastValidEurUsdPrice).

getVaultMetrics() → (uint256, uint256, uint256, uint256, uint256)

function getVaultMetrics() external view returns (
    uint256 totalUsdcHeld_,
    uint256 totalMinted_,
    uint256 totalDebtValue,
    uint256 totalUsdcInExternalVaults_,
    uint256 totalUsdcAvailable_
)

Returns:

  • totalUsdcHeld_: USDC held directly by vault
  • totalMinted_: QEURO minted by vault tracker
  • totalDebtValue: USD debt value using live token supply and cached EUR/USD
  • totalUsdcInExternalVaults_: Principal tracker across all configured external vault adapters
  • totalUsdcAvailable_: Total collateral available including accrued external-vault yield

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 + currentExternalVaultCollateral (includes accrued adapter yield when queryable)
  • 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.

getProtocolCollateralizationRatioView() / canMintView()

View-safe aliases exposing the same logic for off-chain tooling.

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.

harvestVaultYield(uint256 vaultId) → (uint256 harvestedYield)

Governance entrypoint that triggers yield harvest for a specific adapter.


QEUROToken

Contract: QEUROToken.sol
Interface: IQEUROToken.sol
Inherits: ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable

Function Signatures

mint(address to, uint256 amount)

function mint(address to, uint256 amount) external

Modifiers: onlyRole(VAULT_ROLE)
Events: TokensMinted(address indexed to, uint256 amount)

burn(uint256 amount)

function burn(uint256 amount) external

Modifiers: onlyRole(VAULT_ROLE)
Events: TokensBurned(address indexed from, uint256 amount)

whitelistAddress(address account)

function whitelistAddress(address account) external

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

blacklistAddress(address account)

function blacklistAddress(address account) external

Modifiers: onlyRole(COMPLIANCE_ROLE)
Events: AddressBlacklisted(address indexed account)

updateMaxSupply(uint256 newMaxSupply)

function updateMaxSupply(uint256 newMaxSupply) external

Modifiers: onlyRole(ADMIN_ROLE)
Events: MaxSupplyUpdated(uint256 oldMaxSupply, uint256 newMaxSupply)

getTokenInfo() → (uint256, uint256, uint256, bool, bool)

function getTokenInfo() external view returns (
    uint256 totalSupply,
    uint256 maxSupply,
    uint256 supplyUtilization,
    bool whitelistMode,
    bool isPaused
)

QTIToken

Contract: QTIToken.sol
Interface: IQTIToken.sol
Inherits: ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable

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

UserPool

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

Function Signatures

deposit(uint256 usdcAmount)

function deposit(uint256 usdcAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: USDCDeposited(address indexed user, uint256 amount)
Requirements:

  • usdcAmount > 0
  • Sufficient USDC balance and allowance

withdraw(uint256 usdcAmount)

function withdraw(uint256 usdcAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: USDCWithdrawn(address indexed user, uint256 amount)
Requirements:

  • usdcAmount > 0
  • Sufficient balance

stake(uint256 qeuroAmount)

function stake(uint256 qeuroAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: QEUROStaked(address indexed user, uint256 amount)
Requirements:

  • qeuroAmount >= MIN_STAKE_AMOUNT
  • Sufficient QEURO balance and allowance

unstake(uint256 qeuroAmount)

function unstake(uint256 qeuroAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: QEUROUnstaked(address indexed user, uint256 amount)
Requirements:

  • qeuroAmount > 0
  • Sufficient staked balance
  • Cooldown period completed

claimStakingRewards() → (uint256)

function claimStakingRewards() external returns (uint256 rewardAmount)

Modifiers: whenNotPaused, nonReentrant
Events: RewardsClaimed(address indexed user, uint256 amount)

getUserInfo(address user) → (uint256, uint256, uint256, uint256, uint256)

function getUserInfo(address user) external view returns (
    uint256 depositedUsdc,
    uint256 stakedQeuro,
    uint256 lastStakeTime,
    uint256 pendingRewards,
    uint256 totalRewardsClaimed
)

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

function getPoolMetrics() external view returns (
    uint256 totalUsers,
    uint256 totalStakes,
    uint256 totalDeposits,
    uint256 totalRewards
)

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 positionData)
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: HedgingRewardsClaimed(address indexed hedger, bytes32 packedData)
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/rotation proposal.
If no hedger is currently configured, assignment is immediate. Otherwise it creates a delayed pending rotation.

applySingleHedgerRotation()

Executes a pending single-hedger rotation after delay.

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

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_);

getStQEUROByVault(address vault) -> (address)

function getStQEUROByVault(address vault) external view returns (address stQEUROToken_);

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.


stQEUROToken

Contract: stQEUROToken.sol
Interface: IstQEURO.sol
Inherits: ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable

Function Signatures

stake(uint256 qeuroAmount)

function stake(uint256 qeuroAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 stQeuroAmount)
Requirements:

  • qeuroAmount > 0
  • Sufficient QEURO balance and allowance

unstake(uint256 stQeuroAmount)

function unstake(uint256 stQeuroAmount) external

Modifiers: whenNotPaused, nonReentrant
Events: QEUROUnstaked(address indexed user, uint256 stQeuroAmount, uint256 qeuroAmount)
Requirements:

  • stQeuroAmount > 0
  • Sufficient stQEURO balance

claimYield() → (uint256)

function claimYield() external returns (uint256 yieldAmount)

Modifiers: whenNotPaused, nonReentrant
Events: YieldClaimed(address indexed user, uint256 amount)

getExchangeRate() → (uint256)

function getExchangeRate() external view returns (uint256 rate)

Returns: Exchange rate between stQEURO and QEURO (18 decimals)

getQEUROEquivalent(uint256 stQeuroAmount) → (uint256)

function getQEUROEquivalent(uint256 stQeuroAmount) external view returns (uint256 qeuroAmount)

distributeYield(uint256 qeuroAmount)

function distributeYield(uint256 qeuroAmount) external

Modifiers: onlyRole(YIELD_MANAGER_ROLE)
Events: YieldDistributed(uint256 totalAmount, uint256 timestamp)
Requirements:

  • qeuroAmount > 0
  • Sufficient QEURO balance

initialize(...) (metadata overload for factory)

stQEUROToken now supports an overloaded initializer that accepts:

  • tokenName
  • tokenSymbol
  • vaultName

This overload is used by stQEUROFactory when deploying a dedicated proxy per vault.


AaveVault

Contract: AaveVault.sol
Interface: IAaveVault.sol
Inherits: SecureUpgradeable, PausableUpgradeable

Function Signatures

deployToAave(uint256 usdcAmount)

function deployToAave(uint256 usdcAmount) external

Modifiers: onlyRole(YIELD_MANAGER_ROLE), whenNotPaused, nonReentrant
Events: USDCDepositedToAave(uint256 amount)
Requirements:

  • usdcAmount > 0
  • Within exposure limits
  • Sufficient USDC balance

withdrawFromAave(uint256 usdcAmount)

function withdrawFromAave(uint256 usdcAmount) external

Modifiers: onlyRole(YIELD_MANAGER_ROLE), whenNotPaused, nonReentrant
Events: USDCWithdrawnFromAave(uint256 amount)

harvestAaveYield() → (uint256)

function harvestAaveYield() external returns (uint256 yieldAmount)

Modifiers: onlyRole(YIELD_MANAGER_ROLE), whenNotPaused, nonReentrant
Events: AaveYieldHarvested(uint256 amount) Notes:

  • Reverts if yieldVaultId == 0
  • Routes harvested amount through yieldShift.addYield(yieldVaultId, netYield, bytes32("aave"))

setYieldVaultId(uint256 newYieldVaultId)

function setYieldVaultId(uint256 newYieldVaultId) external

Modifiers: onlyRole(GOVERNANCE_ROLE)
Requirements:

  • newYieldVaultId > 0

updateYieldShift(address newYieldShift)

function updateYieldShift(address newYieldShift) external

Modifiers: onlyRole(GOVERNANCE_ROLE)

getAaveBalance() → (uint256)

function getAaveBalance() external view returns (uint256 balance)

getAaveAPY() → (uint256)

function getAaveAPY() external view returns (uint256 apy)

Returns: APY in basis points

autoRebalance() → (bool, uint256, uint256)

function autoRebalance() external returns (
    bool rebalanced,
    uint256 newAllocation,
    uint256 expectedYield
)

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: onlyAuthorizedYieldSource, whenNotPaused, nonReentrant
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 userPoolYield, uint256 hedgerPoolYield, uint256 currentShift)

claimUserYield(address user) → (uint256)

function claimUserYield(address user) external returns (uint256 yieldAmount)

Modifiers: whenNotPaused, nonReentrant
Events: UserYieldClaimed(address indexed user, uint256 yieldAmount, uint256 timestamp)

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
  • aaveVault
  • 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.


ChainlinkOracle

Contract: ChainlinkOracle.sol
Interface: IChainlinkOracle.sol
Inherits: SecureUpgradeable, PausableUpgradeable

Function Signatures

getEurUsdPrice() → (uint256, bool)

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

Returns:

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

getUsdcUsdPrice() → (uint256, bool)

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

Returns:

  • price: USDC/USD price (8 decimals)
  • isValid: Whether price is fresh and valid

updatePriceFeeds(address eurUsdFeed, address usdcUsdFeed)

function updatePriceFeeds(address eurUsdFeed, address usdcUsdFeed) external

Modifiers: onlyRole(ADMIN_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(ADMIN_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(ADMIN_ROLE)
Events: CircuitBreakerReset(uint256 timestamp)


Access Control Roles

RoleDescriptionKey Functions
DEFAULT_ADMIN_ROLESuper adminAll administrative functions
EMERGENCY_ROLEEmergency operationsPause/unpause, circuit breaker
GOVERNANCE_ROLEGovernance operationsParameter updates, proposals
VAULT_ROLEVault operationsMint/burn QEURO
YIELD_MANAGER_ROLEYield managementDistribute yield, manage Aave
COMPLIANCE_ROLECompliance operationsWhitelist/blacklist addresses
LIQUIDATOR_ROLELiquidation operationsLiquidate positions
TIME_MANAGER_ROLETime managementSet time offsets

Constants and Limits

QuantillonVault

  • MAX_MINT_AMOUNT: 1,000,000 USDC
  • MIN_MINT_AMOUNT: 1 USDC
  • MAX_REDEEM_AMOUNT: 1,000,000 QEURO
  • MIN_REDEEM_AMOUNT: 1 QEURO

QEUROToken

  • MAX_SUPPLY: 1,000,000,000 QEURO (1B tokens)
  • MIN_PRICE_PRECISION: 2 decimals
  • MAX_PRICE_PRECISION: 8 decimals

QTIToken

  • MIN_LOCK_TIME: 1 week (604,800 seconds)
  • MAX_LOCK_TIME: 4 years (126,144,000 seconds)
  • MIN_PROPOSAL_POWER: 1,000 veQTI
  • VOTING_PERIOD: 7 days (604,800 seconds)

UserPool

  • MIN_STAKE_AMOUNT: 100 QEURO
  • MAX_STAKE_AMOUNT: 10,000,000 QEURO
  • UNSTAKE_COOLDOWN: 7 days (604,800 seconds)

HedgerPool

  • MAX_LEVERAGE: 10x
  • MIN_LEVERAGE: 1x
  • MIN_MARGIN_RATIO: 110% (1.1)
  • LIQUIDATION_THRESHOLD: 105% (1.05)
  • MAX_POSITIONS_PER_HEDGER: 50

AaveVault

  • MAX_AAVE_EXPOSURE: 80% of total USDC
  • MIN_AAVE_EXPOSURE: 0%
  • REBALANCE_THRESHOLD: 5% deviation

Error Handling

All functions use custom errors for gas efficiency. Common error patterns:

// Revert with custom error
if (condition) revert CustomError();

// Emit event and revert
emit EventName();
revert CustomError();

Error Categories

  1. Access Control Errors

    • UnauthorizedAccess()
    • InsufficientRole()
    • InvalidRole()
  2. Validation Errors

    • InvalidAmount()
    • InvalidAddress()
    • InvalidParameter()
    • InvalidTime()
  3. Business Logic Errors

    • InsufficientBalance()
    • InsufficientAllowance()
    • ExceedsLimit()
    • BelowMinimum()
  4. Oracle Errors

    • StalePrice()
    • InvalidPrice()
    • CircuitBreakerActive()
  5. Emergency Errors

    • ContractPaused()
    • EmergencyMode()

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 Estimates

FunctionGas Cost (approx.)
mintQEURO150,000
redeemQEURO140,000
stake120,000
enterHedgePosition200,000
exitHedgePosition180,000
lock160,000
vote100,000

Gas costs are estimates and may vary based on network conditions.


Integration Patterns

Frontend Integration

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

// Call view function
const result = await contract.methods.getVaultMetrics().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.getVaultMetrics().call()

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

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

Quantillon Protocol Quick Start Guide

Getting Started

This guide will help you quickly integrate with the Quantillon Protocol smart contracts.


Prerequisites

  • Node.js 18+ and npm/yarn
  • Web3 library (web3.js, ethers.js, or web3.py)
  • Ethereum wallet (MetaMask, WalletConnect, etc.)
  • USDC tokens for testing

Installation

JavaScript/TypeScript

npm install ethers
# or
yarn add ethers

Python

pip install web3

Basic Integration

1. Connect to the Protocol

import { ethers } from 'ethers';

// Contract ABIs (you'll need to import these from the compiled contracts)
import QuantillonVaultABI from './abis/QuantillonVault.json';
import QEUROTokenABI from './abis/QEUROToken.json';
import UserPoolABI from './abis/UserPool.json';

// Initialize contracts
const vault = new ethers.Contract(vaultAddress, QuantillonVaultABI, provider);
const qeuro = new ethers.Contract(qeuroAddress, QEUROTokenABI, provider);
const userPool = new ethers.Contract(userPoolAddress, UserPoolABI, provider);

2. Mint QEURO

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

// Mint QEURO with slippage protection
const minQeuroOut = usdcAmount * 0.95; // 5% slippage tolerance
await vault.mintQEURO(usdcAmount, minQeuroOut);

3. Stake QEURO for Rewards

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

// Stake QEURO
await userPool.stake(qeuroAmount);

// Claim rewards later
const rewards = await userPool.claimStakingRewards();

4. Participate in Governance

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

// Create a proposal
const proposalId = await qti.createProposal(
    "Update protocol parameters",
    startTime,
    endTime
);

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

Common Patterns

Error Handling

try {
    await vault.mintQEURO(usdcAmount, minQeuroOut);
} catch (error) {
    if (error.message.includes('InsufficientBalance')) {
        console.log('Insufficient USDC balance');
    } else if (error.message.includes('StalePrice')) {
        console.log('Oracle price is stale');
    } else {
        console.log('Transaction failed:', error.message);
    }
}

Event Listening

// Listen for mint events
vault.on('QEUROMinted', (user, usdcAmount, qeuroAmount, price) => {
    console.log(`User ${user} minted ${qeuroAmount} QEURO for ${usdcAmount} USDC`);
});

// Listen for stake events
userPool.on('QEUROStaked', (user, amount) => {
    console.log(`User ${user} staked ${amount} QEURO`);
});

Batch Operations

// Batch multiple operations
const batch = [
    usdc.approve(vaultAddress, usdcAmount),
    vault.mintQEURO(usdcAmount, minQeuroOut),
    qeuro.approve(userPoolAddress, qeuroAmount),
    userPool.stake(qeuroAmount)
];

await Promise.all(batch);

Testing

Local Development

# Clone the repository
git clone https://github.com/Quantillon-Labs/smart-contracts.git
cd smart-contracts/quantillon-protocol

# Install dependencies
forge install

# Build contracts
forge build

# Run tests
forge test

# Run specific test
forge test --match-contract QEUROToken

# Run security analysis
make security  # Runs both Slither and Mythril

Security Best Practices

1. Always Validate Inputs

// Validate amounts
if (usdcAmount <= 0) {
    throw new Error('Invalid USDC amount');
}

// Validate addresses
if (!ethers.utils.isAddress(userAddress)) {
    throw new Error('Invalid address');
}

2. Use Slippage Protection

// Calculate minimum output with slippage
const slippage = 0.05; // 5%
const minQeuroOut = expectedQeuro * (1 - slippage);

3. Check Contract State

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

// Check oracle price freshness
const [price, isValid] = await oracle.getEurUsdPrice();
if (!isValid) {
    throw new Error('Oracle price is invalid');
}

4. Implement Proper Error Handling

// Retry mechanism for failed transactions
async function retryTransaction(txFunction, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            return await txFunction();
        } catch (error) {
            if (i === maxRetries - 1) throw error;
            await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
        }
    }
}

5. Security Analysis

# Run comprehensive security analysis
make security

# Run individual tools
make slither    # Static analysis
make mythril    # Symbolic execution analysis

# Check security reports
ls scripts/results/mythril-reports/   # Mythril reports
ls scripts/results/slither/           # Slither reports
cat scripts/results/natspec-validation-report.txt
cat scripts/results/contract-sizes/contract-sizes-summary.txt

Advanced Features

Yield Optimization

// Check yield opportunities
const userPoolAPY = await userPool.getStakingAPY();
const hedgerPoolAPY = await hedgerPool.getHedgingAPY();

if (userPoolAPY > hedgerPoolAPY) {
    // Stake in user pool
    await userPool.stake(qeuroAmount);
} else {
    // Open hedge position
    await hedgerPool.enterHedgePosition(marginAmount, leverage);
}

Risk Management

// Monitor position health
const positionInfo = await hedgerPool.getPositionInfo(positionId);
const marginRatio = positionInfo.margin / positionInfo.positionSize;

if (marginRatio < 1.1) {
    console.warn('Position is near liquidation threshold');
    // Add margin or close position
}

Governance Participation

// Check voting power
const votingPower = await qti.getVotingPower(userAddress);
const minPower = await qti.MIN_PROPOSAL_POWER();

if (votingPower >= minPower) {
    // Can create proposals
    const proposalId = await qti.createProposal(description, startTime, endTime);
}

Troubleshooting

Common Issues

  1. "Insufficient allowance"

    • Solution: Approve token spending before calling functions
  2. "Contract paused"

    • Solution: Wait for contract to be unpaused or check with protocol team
  3. "Stale oracle price"

    • Solution: Wait for oracle to update or check oracle configuration
  4. "Gas estimation failed"

    • Solution: Increase gas limit or check transaction parameters

Debug Mode

// Enable debug logging
const vault = new QuantillonVault(vaultAddress, provider, { debug: true });

// Check transaction details
const tx = await vault.mintQEURO(usdcAmount, minQeuroOut);
console.log('Transaction hash:', tx.hash);
console.log('Gas used:', tx.gasUsed);

Support

Resources

Community


Examples

Complete Integration Example

import { ethers } from 'ethers';

class QuantillonIntegration {
    constructor(provider, signer) {
        this.provider = provider;
        this.signer = signer;
        this.vault = new ethers.Contract(VAULT_ADDRESS, QuantillonVaultABI, signer);
        this.qeuro = new ethers.Contract(QEURO_ADDRESS, QEUROTokenABI, signer);
        this.userPool = new ethers.Contract(USER_POOL_ADDRESS, UserPoolABI, signer);
    }

    async mintQEURO(usdcAmount, slippage = 0.05) {
        try {
            // Check contract state
            if (await this.vault.paused()) {
                throw new Error('Contract is paused');
            }

            // Calculate minimum output
            const expectedQeuro = await this.vault.calculateMintAmount(usdcAmount);
            const minQeuroOut = expectedQeuro.mul(100 - slippage * 100).div(100);

            // Approve USDC spending
            const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, this.signer);
            await usdc.approve(VAULT_ADDRESS, usdcAmount);

            // Mint QEURO
            const tx = await this.vault.mintQEURO(usdcAmount, minQeuroOut);
            await tx.wait();

            console.log('QEURO minted successfully');
            return tx;
        } catch (error) {
            console.error('Minting failed:', error.message);
            throw error;
        }
    }

    async stakeQEURO(qeuroAmount) {
        try {
            // Approve QEURO spending
            await this.qeuro.approve(USER_POOL_ADDRESS, qeuroAmount);

            // Stake QEURO
            const tx = await this.userPool.stake(qeuroAmount);
            await tx.wait();

            console.log('QEURO staked successfully');
            return tx;
        } catch (error) {
            console.error('Staking failed:', error.message);
            throw error;
        }
    }

    async getPortfolio(userAddress) {
        try {
            const [vaultMetrics, userInfo, qeuroBalance] = await Promise.all([
                this.vault.getVaultMetrics(),
                this.userPool.getUserInfo(userAddress),
                this.qeuro.balanceOf(userAddress)
            ]);

            return {
                qeuroBalance: qeuroBalance.toString(),
                stakedAmount: userInfo.stakedQeuro.toString(),
                pendingRewards: userInfo.pendingRewards.toString(),
                totalDeposits: userInfo.depositedUsdc.toString(),
                vaultMetrics: {
                    totalReserves: vaultMetrics.totalUsdcReserves.toString(),
                    totalSupply: vaultMetrics.totalQeuroSupply.toString(),
                    collateralizationRatio: vaultMetrics.collateralizationRatio.toString()
                }
            };
        } catch (error) {
            console.error('Failed to get portfolio:', error.message);
            throw error;
        }
    }
}

// Usage
const integration = new QuantillonIntegration(provider, signer);
await integration.mintQEURO(ethers.utils.parseUnits('1000', 6)); // 1000 USDC
await integration.stakeQEURO(ethers.utils.parseUnits('500', 18)); // 500 QEURO
const portfolio = await integration.getPortfolio(userAddress);

This quick start guide is maintained by Quantillon Labs and updated regularly.

Quantillon Protocol Integration Examples

This document provides practical integration examples for common use cases with the Quantillon Protocol.


Table of Contents

  1. Basic QEURO Operations
  2. Staking and Yield Generation
  3. Governance Participation
  4. Hedging Operations
  5. Advanced Integration Patterns
  6. Error Handling and Recovery

Basic QEURO Operations

Minting QEURO from USDC

const { ethers } = require('ethers');

async function mintQEURO(usdcAmount, slippage = 0.05) {
    // Initialize contracts
    const vault = new ethers.Contract(VAULT_ADDRESS, VAULT_ABI, signer);
    const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, signer);
    
    try {
        // 1. Check vault state
        const isPaused = await vault.paused();
        if (isPaused) {
            throw new Error('Vault is paused');
        }
        
        // 2. Calculate expected output
        const expectedQeuro = await vault.calculateMintAmount(usdcAmount);
        const minQeuroOut = expectedQeuro.mul(100 - slippage * 100).div(100);
        
        // 3. Approve USDC spending
        const approveTx = await usdc.approve(VAULT_ADDRESS, usdcAmount);
        await approveTx.wait();
        
        // 4. Mint QEURO
        const mintTx = await vault.mintQEURO(usdcAmount, minQeuroOut);
        const receipt = await mintTx.wait();
        
        // 5. Parse events
        const mintEvent = receipt.events.find(e => e.event === 'QEUROMinted');
        console.log(`Minted ${mintEvent.args.qeuroAmount} QEURO for ${mintEvent.args.usdcAmount} USDC`);
        
        return receipt;
    } catch (error) {
        console.error('Minting failed:', error.message);
        throw error;
    }
}

// Usage
const usdcAmount = ethers.utils.parseUnits('1000', 6); // 1000 USDC
await mintQEURO(usdcAmount, 0.05); // 5% slippage tolerance

Redeeming QEURO for USDC

async function redeemQEURO(qeuroAmount, slippage = 0.05) {
    const vault = new ethers.Contract(VAULT_ADDRESS, VAULT_ABI, signer);
    const qeuro = new ethers.Contract(QEURO_ADDRESS, QEURO_ABI, signer);
    
    try {
        // 1. Calculate expected output
        const expectedUsdc = await vault.calculateRedeemAmount(qeuroAmount);
        const minUsdcOut = expectedUsdc.mul(100 - slippage * 100).div(100);
        
        // 2. Approve QEURO spending
        const approveTx = await qeuro.approve(VAULT_ADDRESS, qeuroAmount);
        await approveTx.wait();
        
        // 3. Redeem QEURO
        const redeemTx = await vault.redeemQEURO(qeuroAmount, minUsdcOut);
        const receipt = await redeemTx.wait();
        
        // 4. Parse events
        const redeemEvent = receipt.events.find(e => e.event === 'QEURORedeemed');
        console.log(`Redeemed ${redeemEvent.args.qeuroAmount} QEURO for ${redeemEvent.args.usdcAmount} USDC`);
        
        return receipt;
    } catch (error) {
        console.error('Redemption failed:', error.message);
        throw error;
    }
}

Staking and Yield Generation

Staking QEURO in User Pool

async function stakeQEURO(qeuroAmount) {
    const userPool = new ethers.Contract(USER_POOL_ADDRESS, USER_POOL_ABI, signer);
    const qeuro = new ethers.Contract(QEURO_ADDRESS, QEURO_ABI, signer);
    
    try {
        // 1. Check minimum stake amount
        const minStakeAmount = await userPool.MIN_STAKE_AMOUNT();
        if (qeuroAmount.lt(minStakeAmount)) {
            throw new Error(`Amount below minimum stake: ${minStakeAmount}`);
        }
        
        // 2. Check user's QEURO balance
        const balance = await qeuro.balanceOf(signer.address);
        if (balance.lt(qeuroAmount)) {
            throw new Error('Insufficient QEURO balance');
        }
        
        // 3. Approve QEURO spending
        const approveTx = await qeuro.approve(USER_POOL_ADDRESS, qeuroAmount);
        await approveTx.wait();
        
        // 4. Stake QEURO
        const stakeTx = await userPool.stake(qeuroAmount);
        const receipt = await stakeTx.wait();
        
        console.log(`Staked ${qeuroAmount} QEURO successfully`);
        return receipt;
    } catch (error) {
        console.error('Staking failed:', error.message);
        throw error;
    }
}

Claiming Staking Rewards

async function claimStakingRewards() {
    const userPool = new ethers.Contract(USER_POOL_ADDRESS, USER_POOL_ABI, signer);
    
    try {
        // 1. Check pending rewards
        const userInfo = await userPool.getUserInfo(signer.address);
        const pendingRewards = userInfo.pendingRewards;
        
        if (pendingRewards.eq(0)) {
            console.log('No rewards to claim');
            return null;
        }
        
        // 2. Claim rewards
        const claimTx = await userPool.claimStakingRewards();
        const receipt = await claimTx.wait();
        
        // 3. Parse events
        const claimEvent = receipt.events.find(e => e.event === 'RewardsClaimed');
        console.log(`Claimed ${claimEvent.args.amount} QEURO rewards`);
        
        return receipt;
    } catch (error) {
        console.error('Claiming rewards failed:', error.message);
        throw error;
    }
}

Staking in stQEURO Token

async function stakeInStQEURO(qeuroAmount) {
    const stQeuro = new ethers.Contract(ST_QEURO_ADDRESS, ST_QEURO_ABI, signer);
    const qeuro = new ethers.Contract(QEURO_ADDRESS, QEURO_ABI, signer);
    
    try {
        // 1. Get current exchange rate
        const exchangeRate = await stQeuro.getExchangeRate();
        const expectedStQeuro = qeuroAmount.mul(ethers.utils.parseEther('1')).div(exchangeRate);
        
        // 2. Approve QEURO spending
        const approveTx = await qeuro.approve(ST_QEURO_ADDRESS, qeuroAmount);
        await approveTx.wait();
        
        // 3. Stake QEURO
        const stakeTx = await stQeuro.stake(qeuroAmount);
        const receipt = await stakeTx.wait();
        
        console.log(`Staked ${qeuroAmount} QEURO, received ${expectedStQeuro} stQEURO`);
        return receipt;
    } catch (error) {
        console.error('stQEURO staking failed:', error.message);
        throw error;
    }
}

Governance Participation

Locking QTI for Voting Power

async function lockQTI(amount, lockDuration) {
    const qti = new ethers.Contract(QTI_ADDRESS, QTI_ABI, signer);
    
    try {
        // 1. Check lock duration limits
        const minLockTime = await qti.MIN_LOCK_TIME();
        const maxLockTime = await qti.MAX_LOCK_TIME();
        
        if (lockDuration.lt(minLockTime) || lockDuration.gt(maxLockTime)) {
            throw new Error(`Lock duration must be between ${minLockTime} and ${maxLockTime} seconds`);
        }
        
        // 2. Check QTI balance
        const balance = await qti.balanceOf(signer.address);
        if (balance.lt(amount)) {
            throw new Error('Insufficient QTI balance');
        }
        
        // 3. Lock QTI
        const lockTx = await qti.lock(amount, lockDuration);
        const receipt = await lockTx.wait();
        
        // 4. Parse events
        const lockEvent = receipt.events.find(e => e.event === 'TokensLocked');
        console.log(`Locked ${amount} QTI for ${lockDuration} seconds, received ${lockEvent.args.votingPower} veQTI`);
        
        return receipt;
    } catch (error) {
        console.error('QTI locking failed:', error.message);
        throw error;
    }
}

Creating a Governance Proposal

async function createProposal(description, startTime, endTime) {
    const qti = new ethers.Contract(QTI_ADDRESS, QTI_ABI, signer);
    
    try {
        // 1. Check voting power
        const votingPower = await qti.getVotingPower(signer.address);
        const minProposalPower = await qti.MIN_PROPOSAL_POWER();
        
        if (votingPower.lt(minProposalPower)) {
            throw new Error(`Insufficient voting power. Required: ${minProposalPower}, Current: ${votingPower}`);
        }
        
        // 2. Validate time parameters
        const currentTime = Math.floor(Date.now() / 1000);
        if (startTime <= currentTime || endTime <= startTime) {
            throw new Error('Invalid time parameters');
        }
        
        // 3. Create proposal
        const proposalTx = await qti.createProposal(description, startTime, endTime);
        const receipt = await proposalTx.wait();
        
        // 4. Parse events
        const proposalEvent = receipt.events.find(e => e.event === 'ProposalCreated');
        console.log(`Created proposal ${proposalEvent.args.proposalId}: ${description}`);
        
        return proposalEvent.args.proposalId;
    } catch (error) {
        console.error('Proposal creation failed:', error.message);
        throw error;
    }
}

Voting on Proposals

async function voteOnProposal(proposalId, support) {
    const qti = new ethers.Contract(QTI_ADDRESS, QTI_ABI, signer);
    
    try {
        // 1. Check voting power
        const votingPower = await qti.getVotingPower(signer.address);
        if (votingPower.eq(0)) {
            throw new Error('No voting power available');
        }
        
        // 2. Check if already voted
        const hasVoted = await qti.hasVoted(proposalId, signer.address);
        if (hasVoted) {
            throw new Error('Already voted on this proposal');
        }
        
        // 3. Vote
        const voteTx = await qti.vote(proposalId, support);
        const receipt = await voteTx.wait();
        
        // 4. Parse events
        const voteEvent = receipt.events.find(e => e.event === 'VoteCast');
        console.log(`Voted ${support ? 'YES' : 'NO'} on proposal ${proposalId} with ${voteEvent.args.votingPower} voting power`);
        
        return receipt;
    } catch (error) {
        console.error('Voting failed:', error.message);
        throw error;
    }
}

Hedging Operations

Opening a Hedge Position

async function openHedgePosition(marginAmount, leverage) {
    const hedgerPool = new ethers.Contract(HEDGER_POOL_ADDRESS, HEDGER_POOL_ABI, signer);
    const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, signer);
    
    try {
        // 1. Validate leverage
        const maxLeverage = await hedgerPool.maxLeverage();
        if (leverage.lt(1) || leverage.gt(maxLeverage)) {
            throw new Error(`Leverage must be between 1 and ${maxLeverage}`);
        }
        
        // 2. Check USDC balance
        const balance = await usdc.balanceOf(signer.address);
        if (balance.lt(marginAmount)) {
            throw new Error('Insufficient USDC balance');
        }
        
        // 3. Approve USDC spending
        const approveTx = await usdc.approve(HEDGER_POOL_ADDRESS, marginAmount);
        await approveTx.wait();
        
        // 4. Open position
        const openTx = await hedgerPool.enterHedgePosition(marginAmount, leverage);
        const receipt = await openTx.wait();
        
        // 5. Parse events
        const openEvent = receipt.events.find(e => e.event === 'HedgePositionOpened');
        console.log(`Opened position ${openEvent.args.positionId} with ${marginAmount} USDC margin and ${leverage}x leverage`);
        
        return openEvent.args.positionId;
    } catch (error) {
        console.error('Opening position failed:', error.message);
        throw error;
    }
}

Monitoring Position Health

async function monitorPosition(positionId) {
    const hedgerPool = new ethers.Contract(HEDGER_POOL_ADDRESS, HEDGER_POOL_ABI, signer);
    
    try {
        // 1. Get position info
        const positionInfo = await hedgerPool.getPositionInfo(positionId);
        
        // 2. Calculate margin ratio
        const marginRatio = positionInfo.margin.mul(10000).div(positionInfo.positionSize);
        const liquidationThreshold = await hedgerPool.liquidationThreshold();
        
        // 3. Check if position is healthy
        const isHealthy = marginRatio.gt(liquidationThreshold);
        
        console.log(`Position ${positionId}:`);
        console.log(`  Margin: ${ethers.utils.formatUnits(positionInfo.margin, 6)} USDC`);
        console.log(`  Position Size: ${ethers.utils.formatUnits(positionInfo.positionSize, 6)} USDC`);
        console.log(`  Margin Ratio: ${marginRatio.toNumber() / 100}%`);
        console.log(`  Unrealized PnL: ${ethers.utils.formatEther(positionInfo.unrealizedPnL)} QEURO`);
        console.log(`  Status: ${isHealthy ? 'HEALTHY' : 'AT RISK'}`);
        
        return {
            positionInfo,
            marginRatio,
            isHealthy
        };
    } catch (error) {
        console.error('Position monitoring failed:', error.message);
        throw error;
    }
}

Adding Margin to Position

async function addMargin(positionId, additionalMargin) {
    const hedgerPool = new ethers.Contract(HEDGER_POOL_ADDRESS, HEDGER_POOL_ABI, signer);
    const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, signer);
    
    try {
        // 1. Check position ownership
        const positionInfo = await hedgerPool.getPositionInfo(positionId);
        if (positionInfo.hedger !== signer.address) {
            throw new Error('Not the owner of this position');
        }
        
        // 2. Check USDC balance
        const balance = await usdc.balanceOf(signer.address);
        if (balance.lt(additionalMargin)) {
            throw new Error('Insufficient USDC balance');
        }
        
        // 3. Approve USDC spending
        const approveTx = await usdc.approve(HEDGER_POOL_ADDRESS, additionalMargin);
        await approveTx.wait();
        
        // 4. Add margin
        const addMarginTx = await hedgerPool.addMargin(positionId, additionalMargin);
        const receipt = await addMarginTx.wait();
        
        console.log(`Added ${ethers.utils.formatUnits(additionalMargin, 6)} USDC margin to position ${positionId}`);
        return receipt;
    } catch (error) {
        console.error('Adding margin failed:', error.message);
        throw error;
    }
}

Advanced Integration Patterns

Portfolio Management

class QuantillonPortfolio {
    constructor(provider, signer) {
        this.provider = provider;
        this.signer = signer;
        this.vault = new ethers.Contract(VAULT_ADDRESS, VAULT_ABI, signer);
        this.qeuro = new ethers.Contract(QEURO_ADDRESS, QEURO_ABI, signer);
        this.userPool = new ethers.Contract(USER_POOL_ADDRESS, USER_POOL_ABI, signer);
        this.hedgerPool = new ethers.Contract(HEDGER_POOL_ADDRESS, HEDGER_POOL_ABI, signer);
    }
    
    async getPortfolioOverview() {
        const address = this.signer.address;
        
        try {
            const [
                qeuroBalance,
                userInfo,
                vaultMetrics,
                positions
            ] = await Promise.all([
                this.qeuro.balanceOf(address),
                this.userPool.getUserInfo(address),
                this.vault.getVaultMetrics(),
                this.getUserPositions()
            ]);
            
            return {
                balances: {
                    qeuro: ethers.utils.formatEther(qeuroBalance),
                    staked: ethers.utils.formatEther(userInfo.stakedQeuro),
                    deposited: ethers.utils.formatUnits(userInfo.depositedUsdc, 6)
                },
                rewards: {
                    pending: ethers.utils.formatEther(userInfo.pendingRewards),
                    claimed: ethers.utils.formatEther(userInfo.totalRewardsClaimed)
                },
                positions: positions,
                vault: {
                    totalReserves: ethers.utils.formatUnits(vaultMetrics.totalUsdcReserves, 6),
                    totalSupply: ethers.utils.formatEther(vaultMetrics.totalQeuroSupply),
                    collateralizationRatio: vaultMetrics.collateralizationRatio.toNumber() / 100
                }
            };
        } catch (error) {
            console.error('Failed to get portfolio overview:', error.message);
            throw error;
        }
    }
    
    async getUserPositions() {
        // Implementation to get user's hedge positions
        // This would require tracking position IDs or using events
        return [];
    }
    
    async optimizeYield() {
        try {
            const userPoolAPY = await this.userPool.getStakingAPY();
            const hedgerPoolAPY = await this.hedgerPool.getHedgingAPY();
            
            console.log(`User Pool APY: ${userPoolAPY.toNumber() / 100}%`);
            console.log(`Hedger Pool APY: ${hedgerPoolAPY.toNumber() / 100}%`);
            
            if (userPoolAPY.gt(hedgerPoolAPY)) {
                console.log('Recommendation: Stake in User Pool for higher yield');
            } else {
                console.log('Recommendation: Consider hedging for higher yield');
            }
        } catch (error) {
            console.error('Yield optimization failed:', error.message);
            throw error;
        }
    }
}

// Usage
const portfolio = new QuantillonPortfolio(provider, signer);
const overview = await portfolio.getPortfolioOverview();
console.log('Portfolio Overview:', overview);
await portfolio.optimizeYield();

Automated Yield Management

class YieldManager {
    constructor(provider, signer) {
        this.provider = provider;
        this.signer = signer;
        this.yieldShift = new ethers.Contract(YIELD_SHIFT_ADDRESS, YIELD_SHIFT_ABI, signer);
        this.aaveVault = new ethers.Contract(AAVE_VAULT_ADDRESS, AAVE_VAULT_ABI, signer);
    }
    
    async checkAndDistributeYield() {
        try {
            // 1. Check if yield distribution is needed
            const poolMetrics = await this.yieldShift.getPoolMetrics();
            const targetRatio = await this.yieldShift.targetPoolRatio();
            
            const currentRatio = poolMetrics.userPoolSize.mul(10000).div(poolMetrics.hedgerPoolSize);
            const deviation = currentRatio.sub(targetRatio).abs();
            const threshold = await this.yieldShift.rebalanceThreshold();
            
            if (deviation.gt(threshold)) {
                console.log('Pool ratio deviation detected, distributing yield...');
                await this.yieldShift.distributeYield();
            }
        } catch (error) {
            console.error('Yield distribution failed:', error.message);
            throw error;
        }
    }
    
    async harvestAaveYield() {
        try {
            const yieldAmount = await this.aaveVault.harvestAaveYield();
            console.log(`Harvested ${ethers.utils.formatEther(yieldAmount)} QEURO from Aave`);
            return yieldAmount;
        } catch (error) {
            console.error('Aave yield harvest failed:', error.message);
            throw error;
        }
    }
    
    async autoRebalance() {
        try {
            const [rebalanced, newAllocation, expectedYield] = await this.aaveVault.autoRebalance();
            
            if (rebalanced) {
                console.log(`Rebalanced to ${newAllocation.toNumber() / 100}% allocation`);
                console.log(`Expected yield: ${ethers.utils.formatEther(expectedYield)} QEURO`);
            } else {
                console.log('No rebalancing needed');
            }
            
            return { rebalanced, newAllocation, expectedYield };
        } catch (error) {
            console.error('Auto rebalancing failed:', error.message);
            throw error;
        }
    }
}

Error Handling and Recovery

Comprehensive Error Handling

class QuantillonErrorHandler {
    static handleError(error) {
        const errorMessage = error.message.toLowerCase();
        
        if (errorMessage.includes('insufficient balance')) {
            return {
                type: 'INSUFFICIENT_BALANCE',
                message: 'Insufficient token balance for this operation',
                action: 'Check your token balance and try again'
            };
        } else if (errorMessage.includes('insufficient allowance')) {
            return {
                type: 'INSUFFICIENT_ALLOWANCE',
                message: 'Token allowance is insufficient',
                action: 'Approve token spending before calling this function'
            };
        } else if (errorMessage.includes('stale price')) {
            return {
                type: 'STALE_PRICE',
                message: 'Oracle price is stale',
                action: 'Wait for oracle to update or contact support'
            };
        } else if (errorMessage.includes('contract paused')) {
            return {
                type: 'CONTRACT_PAUSED',
                message: 'Contract is currently paused',
                action: 'Wait for contract to be unpaused'
            };
        } else if (errorMessage.includes('unauthorized')) {
            return {
                type: 'UNAUTHORIZED',
                message: 'Unauthorized access',
                action: 'Check your permissions and try again'
            };
        } else {
            return {
                type: 'UNKNOWN',
                message: error.message,
                action: 'Contact support if the issue persists'
            };
        }
    }
    
    static async retryOperation(operation, maxRetries = 3, delay = 1000) {
        for (let i = 0; i < maxRetries; i++) {
            try {
                return await operation();
            } catch (error) {
                const errorInfo = this.handleError(error);
                
                if (i === maxRetries - 1) {
                    throw new Error(`${errorInfo.type}: ${errorInfo.message}. ${errorInfo.action}`);
                }
                
                console.log(`Attempt ${i + 1} failed: ${errorInfo.message}. Retrying in ${delay}ms...`);
                await new Promise(resolve => setTimeout(resolve, delay));
                delay *= 2; // Exponential backoff
            }
        }
    }
}

// Usage
try {
    await QuantillonErrorHandler.retryOperation(async () => {
        return await vault.mintQEURO(usdcAmount, minQeuroOut);
    });
} catch (error) {
    console.error('Operation failed after retries:', error.message);
}

Transaction Monitoring

class TransactionMonitor {
    static async waitForConfirmation(tx, confirmations = 1) {
        try {
            console.log(`Transaction submitted: ${tx.hash}`);
            const receipt = await tx.wait(confirmations);
            console.log(`Transaction confirmed in block ${receipt.blockNumber}`);
            return receipt;
        } catch (error) {
            console.error(`Transaction failed: ${error.message}`);
            throw error;
        }
    }
    
    static async monitorGasPrice(provider, maxGasPrice) {
        const gasPrice = await provider.getGasPrice();
        if (gasPrice.gt(maxGasPrice)) {
            console.warn(`Gas price ${ethers.utils.formatUnits(gasPrice, 'gwei')} Gwei exceeds maximum ${ethers.utils.formatUnits(maxGasPrice, 'gwei')} Gwei`);
            return false;
        }
        return true;
    }
    
    static async estimateGasWithBuffer(contract, method, params, buffer = 1.2) {
        try {
            const gasEstimate = await contract.estimateGas[method](...params);
            return gasEstimate.mul(Math.floor(buffer * 100)).div(100);
        } catch (error) {
            console.error('Gas estimation failed:', error.message);
            throw error;
        }
    }
}

Best Practices

1. Always Check Contract State

// Check if contract is paused before any operation
const isPaused = await contract.paused();
if (isPaused) {
    throw new Error('Contract is paused');
}

2. Use Slippage Protection

// Always use slippage protection for swaps
const slippage = 0.05; // 5%
const minOutput = expectedOutput.mul(100 - slippage * 100).div(100);

3. Implement Proper Error Handling

// Use try-catch blocks and handle specific errors
try {
    await contract.function();
} catch (error) {
    const errorInfo = QuantillonErrorHandler.handleError(error);
    console.error(`${errorInfo.type}: ${errorInfo.message}`);
}

4. Monitor Events

// Listen for important events
contract.on('EventName', (param1, param2) => {
    console.log('Event received:', param1, param2);
});

5. Gas Optimization

// Estimate gas and add buffer
const gasEstimate = await contract.estimateGas.function(params);
const gasLimit = gasEstimate.mul(120).div(100); // 20% buffer

This integration examples guide is maintained by Quantillon Labs and updated regularly.

Quantillon Protocol Architecture

Overview

The Quantillon Protocol is a sophisticated DeFi ecosystem built around a euro-pegged stablecoin (QEURO) with advanced yield management and risk mitigation systems. The architecture is designed for scalability, security, and efficient capital utilization.

The staking layer now supports a multi-vault model through stQEUROFactory: each staking vault has its own non-fungible staking token instance (stQEURO{vaultName}).


System Architecture

High-Level Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        SYSTEM ARCHITECTURE                      │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   User Layer    │    │ Protocol Layer  │    │  Yield Layer    │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ • Retail Users  │───▶│ • QuantillonVault│    │ • AaveVault     │
│ • Institutional │    │ • QEUROToken    │    │ • YieldShift    │
│ • Liquidity     │    │ • QTIToken      │    └─────────────────┘
│   Providers     │    │ • FeeCollector  │             │
└─────────────────┘    │ • UserPool      │             │
                       │ • HedgerPool    │             │
                       │ • stQEUROToken  │             │
                       └─────────────────┘             │
                                │                      │
                       ┌─────────────────┐             │
                       │Infrastructure   │             │
                       │Layer            │             │
                       ├─────────────────┤             │
                       │ • OracleRouter  │             │
                       │ • TimeProvider  │             │
                       │ • Security Libs │             │
                       └─────────────────┘             │
                                │                      │
                       ┌─────────────────┐             │
                       │External Systems │             │
                       ├─────────────────┤             │
                       │ • Aave Protocol │◀────────────┘
                       │ • Chainlink     │
                       │ • Stork Network │
                       │ • 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 system
  • 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.

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
  • Voting System: Proposal and execution framework
  • Decay Function: Linear voting power decay

4. UserPool

Purpose: Manages user deposits, staking, and yield distribution.

Key Features:

  • USDC deposit/withdrawal
  • QEURO staking for rewards
  • Yield distribution system
  • User position tracking
  • Reward calculation and claiming

Architecture Patterns:

  • Pool Pattern: Centralized liquidity management
  • Reward Distribution: Proportional yield allocation
  • 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 = (totalUnderlying + totalYieldEarned) / totalSupply
  • 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:

  • Routes price requests to the active oracle (Chainlink or Stork)
  • Governance can switch between oracles at runtime without changing protocol contracts
  • Both oracles implement the same IOracle interface
  • Event emitted on oracle switch (OracleSwitched)

9. ChainlinkOracle / StorkOracle

Purpose: EUR/USD and USDC/USD price feeds with circuit breakers.

Key Features:

  • ChainlinkOracle: Uses Chainlink AggregatorV3 feeds; 1-hour staleness check; 5% deviation circuit breaker
  • StorkOracle: Uses Stork Network TemporalNumericValue feeds; identical staleness/deviation validation
  • Both support EUR/USD and USDC/USD feeds
  • Mock versions available (MockChainlinkOracle, MockStorkOracle) for local/testnet

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: Aave, 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

AaveVault Integration

Purpose: Automated yield generation through Aave protocol.

Features:

  • USDC deployment to Aave
  • Yield harvesting and distribution
  • Risk management and exposure limits
  • Emergency withdrawal mechanisms
  • Auto-rebalancing based on market conditions

Architecture Patterns:

  • Adapter Pattern: Aave protocol integration
  • Risk Management: Exposure limit enforcement
  • Yield Optimization: Dynamic allocation strategies
  • Vault-Aware Routing: Harvested yield is pushed to YieldShift.addYield(yieldVaultId, ...)

Security Architecture

Access Control System

Role-Based Access Control (RBAC):

  • MINTER_ROLE / BURNER_ROLE: QEUROToken — vault-only mint/burn
  • PAUSER_ROLE: QEUROToken emergency pause
  • COMPLIANCE_ROLE: QEUROToken blacklist/whitelist management
  • GOVERNANCE_ROLE: Parameter updates and contract wiring across all core contracts
  • EMERGENCY_ROLE: Emergency pause and withdrawal across all core contracts
  • VAULT_OPERATOR_ROLE: QuantillonVault — authorize Aave deployment
  • HEDGER_ROLE: HedgerPool — open and manage hedging positions
  • TREASURY_ROLE: FeeCollector — fee withdrawal
  • ORACLE_MANAGER_ROLE: OracleRouter/ChainlinkOracle/StorkOracle — feed updates, oracle switching
  • UPGRADER_ROLE: Oracle contracts — UUPS upgrades

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

QEURO Minting Flow:
┌─────────┐    ┌──────────────┐    ┌─────────────────┐    ┌─────────────┐
│  User   │    │QuantillonVault│    │ChainlinkOracle │    │QEUROToken   │
└────┬────┘    └──────┬───────┘    └────────┬────────┘    └──────┬──────┘
     │                │                      │                    │
     │ approve()      │                      │                    │
     ├───────────────▶│                      │                    │
     │ mintQEURO()    │                      │                    │
     ├───────────────▶│                      │                    │
     │                │ getEurUsdPrice()     │                    │
     │                ├─────────────────────▶│                    │
     │                │ price, isValid       │                    │
     │                │◀─────────────────────┤                    │
     │                │ validatePrice()      │                    │
     │                │ calculateMintAmount()│                    │
     │                │ transferFrom()       │                    │
     │                │ mint()               │                    │
     │                ├─────────────────────────────────────────▶│
     │                │ emit QEUROMinted()   │                    │
     │ success        │                      │                    │
     │◀───────────────┤                      │                    │

Yield Distribution Flow

Yield Distribution Flow:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ YieldShift  │    │ AaveVault   │    │  UserPool   │    │ HedgerPool  │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │                  │
       │ harvestAaveYield()│                  │                  │
       ├─────────────────▶│                  │                  │
       │                  │ claimRewards()   │                  │
       │                  ├─────────────────▶│                  │
       │                  │ yieldAmount      │                  │
       │                  │◀─────────────────┤                  │
       │ addYield()       │                  │                  │
       │◀─────────────────┤                  │                  │
       │ calculateOptimalDistribution()      │                  │
       │ distributeUserYield()               │                  │
       ├─────────────────────────────────────▶│                  │
       │ distributeHedgerYield()             │                  │
       ├───────────────────────────────────────────────────────▶│
       │ emit YieldDistributed()             │                  │

Governance Flow

Governance Flow:
┌─────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  User   │    │  QTIToken   │    │  Timelock   │    │   Target    │
│         │    │             │    │             │    │  Contract   │
└────┬────┘    └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
     │                │                  │                  │
     │ lock()         │                  │                  │
     ├───────────────▶│                  │                  │
     │                │ calculateVotingPower()              │
     │                │ emit TokensLocked()                 │
     │ createProposal()│                  │                  │
     ├───────────────▶│                  │                  │
     │                │ validateVotingPower()               │
     │                │ emit ProposalCreated()              │
     │ vote()         │                  │                  │
     ├───────────────▶│                  │                  │
     │                │ emit VoteCast()  │                  │
     │ executeProposal()│                │                  │
     ├───────────────▶│                  │                  │
     │                │ schedule()       │                  │
     │                ├─────────────────▶│                  │
     │                │                  │ execute()        │
     │                │                  ├─────────────────▶│

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:

  • Transparent proxy for admin functions
  • UUPS proxy for gas efficiency
  • Storage layout compatibility
  • Initialization pattern for upgrades

Upgrade Process:

  1. Deploy new implementation
  2. Validate compatibility
  3. Schedule upgrade via governance
  4. Execute upgrade after timelock
  5. Verify functionality

Integration Architecture

External Integrations

Oracle System (OracleRouter + ChainlinkOracle + StorkOracle):

  • OracleRouter implements IOracle — all protocol contracts use this interface
  • Active oracle is switchable by governance (Chainlink ↔ Stork) without contract changes
  • ChainlinkOracle: EUR/USD + USDC/USD via Chainlink AggregatorV3; 1 hr staleness check; 5% deviation circuit breaker
  • StorkOracle: EUR/USD + USDC/USD via Stork Network; same staleness/deviation validation
  • MockChainlinkOracle + MockStorkOracle available for local/testnet development

Aave Protocol:

  • USDC lending integration via AaveVault
  • Yield harvesting and distribution
  • Risk management (exposure limits)
  • Emergency withdrawal mechanisms

ERC-20 Standards:

  • Full ERC-20 compliance
  • Extended functionality
  • Metadata support
  • Permit functionality

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

Future Architecture Considerations

Layer 2 Integration

Planned Support:

  • Polygon deployment
  • Arbitrum integration
  • Optimism support
  • Base network expansion

Cross-Chain Architecture:

  • Bridge integration
  • Cross-chain governance
  • Unified yield management
  • Shared security model

Advanced Features

Planned Enhancements:

  • Advanced yield strategies
  • Institutional features
  • MEV protection
  • Enhanced governance
  • Automated market making

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.

Quantillon Protocol Security Guide

Overview

The Quantillon Protocol implements comprehensive security measures to protect user funds and ensure protocol integrity. This document outlines security best practices, audit reports, 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[Audit Reports]
        BB[Bug Bounty]
        MC[Monitoring & Alerting]
    end

Security Features

1. Access Control

Role-Based Access Control (RBAC):

  • Hierarchical permission system
  • Principle of least privilege
  • Time-locked administrative functions
  • Multi-signature requirements for critical operations

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
COMPLIANCE_ROLE   = keccak256("COMPLIANCE_ROLE");  // Blacklist/whitelist management

// QuantillonVault / UserPool / HedgerPool / YieldShift / AaveVault
GOVERNANCE_ROLE         = keccak256("GOVERNANCE_ROLE");         // Parameter updates, wiring
EMERGENCY_ROLE          = keccak256("EMERGENCY_ROLE");          // Emergency pause/withdraw
VAULT_OPERATOR_ROLE     = keccak256("VAULT_OPERATOR_ROLE");     // Vault: Aave deployment
HEDGER_ROLE             = keccak256("HEDGER_ROLE");             // HedgerPool: open positions

// FeeCollector
TREASURY_ROLE     = keccak256("TREASURY_ROLE");    // Fee withdrawal

// OracleRouter / ChainlinkOracle / StorkOracle
ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE"); // Feed address updates, oracle switching
UPGRADER_ROLE       = keccak256("UPGRADER_ROLE");       // UUPS upgrades

2. Reentrancy Protection

Implementation:

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

Example:

modifier nonReentrant() {
    require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
    _status = _ENTERED;
    _;
    _status = _NOT_ENTERED;
}

3. Oracle Security

Price Feed Validation:

  • Multiple price feed sources
  • Staleness checks (max 1 hour)
  • Price bound validation
  • Circuit breaker mechanisms

Implementation:

function validateOraclePrice(bool isValid) internal pure {
    if (!isValid) revert ErrorLibrary.StalePrice();
}

function validatePriceBounds(uint256 price) internal view {
    if (price < minPrice || price > maxPrice) {
        revert ErrorLibrary.InvalidPrice();
    }
}

4. Emergency Mechanisms

Pause System:

  • Global pause functionality
  • Role-based pause controls
  • Emergency withdrawal capabilities
  • Circuit breaker activation

Implementation:

modifier whenNotPaused() {
    require(!paused(), "Pausable: paused");
    _;
}

function emergencyPause() external onlyRole(EMERGENCY_ROLE) {
    _pause();
    emit EmergencyPause(msg.sender, block.timestamp);
}

Bug Bounty Program

Program Details

Reward Structure:

  • Critical: $100,000
  • High: $50,000
  • Medium: $10,000
  • Low: $1,000
  • Informational: $500

Scope:

  • All smart contracts in the protocol
  • Integration contracts
  • Governance mechanisms
  • Oracle systems

Exclusions:

  • Issues in third-party dependencies
  • Social engineering attacks
  • Physical attacks
  • Issues requiring admin privileges

Submission Process

  1. Report: Submit detailed vulnerability report
  2. Review: Security team reviews submission
  3. Validation: Reproduce and validate issue
  4. Fix: Develop and deploy fix
  5. Reward: Process bounty payment

Contact: security@quantillon.money


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

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 {
    require(amount > 0, "Amount must be positive");
    require(amount <= MAX_DEPOSIT, "Amount exceeds limit");
    // ... function logic
}

Access Control:

modifier onlyAuthorized() {
    require(hasRole(AUTHORIZED_ROLE, msg.sender), "Unauthorized");
    _;
}

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) {
    if (error.message.includes('InsufficientBalance')) {
        // Handle insufficient balance
    } else if (error.message.includes('StalePrice')) {
        // Handle stale price
    } else {
        // Handle other errors
    }
}

2. Monitoring

Event Monitoring:

// Monitor important events
contract.on('QEUROMinted', (user, usdcAmount, qeuroAmount) => {
    console.log(`User ${user} minted ${qeuroAmount} QEURO`);
});

contract.on('EmergencyPause', (admin, timestamp) => {
    console.log(`Contract paused by ${admin} at ${timestamp}`);
});

Health Checks:

async function healthCheck() {
    const [
        isPaused,
        oraclePrice,
        vaultMetrics
    ] = await Promise.all([
        vault.paused(),
        oracle.getEurUsdPrice(),
        vault.getVaultMetrics()
    ]);
    
    if (isPaused) {
        console.warn("Vault is paused");
    }
    
    if (!oraclePrice.isValid) {
        console.warn("Oracle price is stale");
    }
    
    if (vaultMetrics.collateralizationRatio < 11000) {
        console.warn("Low collateralization ratio");
    }
}

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%
  • Liquidity ratio < 110%
  • 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 Team: security@quantillon.money


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

As of March 10, 2026, the latest local validation included:

  • NatSpec coverage: 1218/1218 functions documented (100.00%)
  • Targeted Slither missing-zero-check pass: 0 findings
  • Mock oracle initialization hardening with explicit zero-address validation for admin-derived state

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.

Quantillon Protocol — Deployment Guide

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.


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
            │
            ├── AaveVault + ERC1967Proxy (uses Aave V3 or mock)
            │
            ├── 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.setYieldSourceAuthorization(aaveVault, "aave", true)
  • yieldShift.bootstrapDefaults()
  • aaveVault.updateYieldShift(yieldShift)
  • 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 on initialization.

Network Configuration

NetworkChain IDUSDCAave V3StorkChainlink EUR/USD
Localhost (Anvil)31337Base mainnet USDC or MockUSDCMockMockMock (or real on fork)
Base Sepolia845320x036CbD53842c5426634e7929541eC2318f3dCF7e0xE4C23309117Aa30342BFaae6c95c6478e0A4Ad00 (or mock)Mock0xd30e2101a97dcbAeBCBC04F14C3f624E67A35165
Base Mainnet84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA029130xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64B0x647DFd812BC1e116c6992CB2bC353b2112176fD60xc91D87E81faB8f93699ECf7Ee9B44D11e1D53F0F

Localhost Deployment

Start Anvil

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

# Or fork Base mainnet (allows using real oracle feeds without mocks)
anvil --host 0.0.0.0 --port 8545 --fork-url https://mainnet.base.org --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
  • Falls back to mock Aave if Base Sepolia Aave addresses have no code

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 1M optimizer runs
./scripts/deployment/deploy.sh base --verify --production

The --production flag sets FOUNDRY_PROFILE=production which uses 1,000,000 optimizer runs (defined in foundry.toml).

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.


Accessing Deployed Addresses

Programmatically (shell)

jq '.qeuroToken' deployments/31337/addresses.json
# "0x..."

Frontend format (addresses.json)

{
  "31337": {
    "name": "Anvil Localhost",
    "isTestnet": true,
    "contracts": {
      "timeProvider": "0x...",
      "chainlinkOracle": "0x...",
      "storkOracle": "0x...",
      "oracleRouter": "0x...",
      "feeCollector": "0x...",
      "qeuroToken": "0x...",
      "quantillonVault": "0x...",
      "qtiToken": "0x...",
      "aaveVault": "0x...",
      "stQEUROFactory": "0x...",
      "stQeuroToken": "0x...",
      "userPool": "0x...",
      "hedgerPool": "0x...",
      "yieldShift": "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 0.0.0.0 --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 admin roles to the governance multisig

Never Commit Secrets

  • All .env* files are in .gitignore
  • Use a secret manager (AWS Secrets Manager, HashiCorp Vault) for production CI/CD

Maintained by Quantillon Labs. See scripts/README.md for the complete deployment script reference.

Contents

Contents

IPool

Git Source

Title: AaveVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Note: security-contact: team@quantillon.money

Functions

supply

Supply assets to Aave protocol

Supplies assets to Aave protocol on behalf of 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;

Parameters

NameTypeDescription
assetaddressAddress of the asset to supply
amountuint256Amount of assets to supply
onBehalfOfaddressAddress to supply on behalf of
referralCodeuint16Referral code for Aave protocol

withdraw

Withdraw assets from Aave protocol

Withdraws assets from Aave protocol to a 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function withdraw(address asset, uint256 amount, address to) external returns (uint256);

Parameters

NameTypeDescription
assetaddressAddress of the asset to withdraw
amountuint256Amount of assets to withdraw
toaddressAddress to withdraw to

Returns

NameTypeDescription
<none>uint256uint256 Amount of assets withdrawn

getReserveData

Get reserve data for an asset

Returns reserve data for a specific asset in Aave protocol

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getReserveData(address asset) external view returns (ReserveData memory);

Parameters

NameTypeDescription
assetaddressAddress of the asset

Returns

NameTypeDescription
<none>ReserveDataReserveData Reserve data structure

IPoolAddressesProvider

Git Source

Functions

getPool

Get the pool address

Returns the address of the Aave 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 getPool() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress Address of the Aave pool

IRewardsController

Git Source

Functions

claimRewards

Claim rewards from Aave protocol

Claims rewards for specified assets and amount

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 claimRewards(address[] calldata assets, uint256 amount, address to) external returns (uint256);

Parameters

NameTypeDescription
assetsaddress[]Array of asset addresses
amountuint256Amount of rewards to claim
toaddressAddress to send rewards to

Returns

NameTypeDescription
<none>uint256uint256 Amount of rewards claimed

getUserRewards

Get user rewards for specified assets

Returns the rewards for a user across specified assets

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getUserRewards(address[] calldata assets, address user) external view returns (uint256[] memory);

Parameters

NameTypeDescription
assetsaddress[]Array of asset addresses
useraddressAddress of the user

Returns

NameTypeDescription
<none>uint256[]uint256[] Array of reward amounts for each asset

ReserveData

Git Source

struct ReserveData {
uint256 configuration;
uint128 liquidityIndex;
uint128 currentLiquidityRate;
uint128 variableBorrowIndex;
uint128 currentVariableBorrowRate;
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
uint16 id;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
}

AaveVault

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable, IExternalStakingVault

Title: AaveVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Aave integration vault for yield generation through USDC lending

Main characteristics:

  • USDC deposits into Aave lending protocol for yield generation
  • Automatic yield harvesting and distribution
  • Risk management with exposure limits and health monitoring
  • Emergency withdrawal capabilities for crisis situations
  • Dynamic allocation based on market conditions
  • Upgradeable via UUPS pattern

Deposit mechanics:

  • USDC supplied to Aave protocol for lending
  • Receives aUSDC tokens representing interest-bearing deposits
  • Principal tracking for yield calculation
  • Maximum exposure limits for risk management
  • Health checks before deposits

Yield harvesting:

  • Automatic detection of accrued interest
  • Threshold-based harvesting to optimize gas costs
  • Protocol fees charged on harvested yield
  • Net yield distributed to yield shift mechanism
  • Real-time yield tracking and reporting

Risk management:

  • Maximum Aave exposure limits (default 50M USDC)
  • Utilization rate monitoring for liquidity risk
  • Emergency mode for immediate withdrawals
  • Health monitoring of Aave protocol status
  • Slippage protection on withdrawals

Allocation strategy:

  • Dynamic allocation based on Aave APY
  • Rebalancing thresholds for optimal yield
  • Market condition adjustments
  • Liquidity availability considerations
  • Expected yield calculations

Fee structure:

  • Yield fees charged on harvested interest (default 10%)
  • Protocol fees for sustainability
  • Dynamic fee adjustment based on performance
  • Fee collection and distribution tracking

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 withdrawal validation
  • Health monitoring and circuit breakers

Integration points:

  • Aave lending protocol for yield generation
  • USDC for deposits and withdrawals
  • aUSDC tokens for interest accrual tracking
  • Yield shift mechanism for yield distribution
  • Rewards controller for additional incentives

Note: security-contact: team@quantillon.money

State Variables

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_MANAGER_ROLE

bytes32 public constant VAULT_MANAGER_ROLE = keccak256("VAULT_MANAGER_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

usdc

IERC20 public usdc

aUSDC

IERC20 public aUSDC

aavePool

IPool public aavePool

aaveProvider

IPoolAddressesProvider public aaveProvider

rewardsController

IRewardsController public rewardsController

yieldShift

IYieldShift public yieldShift

maxAaveExposure

uint256 public maxAaveExposure

harvestThreshold

uint256 public harvestThreshold

yieldFee

uint256 public yieldFee

rebalanceThreshold

uint256 public rebalanceThreshold

principalDeposited

uint256 public principalDeposited

lastHarvestTime

uint256 public lastHarvestTime

totalYieldHarvested

uint256 public totalYieldHarvested

totalFeesCollected

uint256 public totalFeesCollected

utilizationLimit

uint256 public utilizationLimit

emergencyExitThreshold

uint256 public emergencyExitThreshold

yieldVaultId

uint256 public yieldVaultId

emergencyMode

bool public emergencyMode

treasury

address public treasury

Functions

constructor

Constructor for AaveVault implementation

Disables initialization on implementation for security

Notes:

  • security: Disables initialization on implementation for security

  • validation: No input validation required

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: Not protected - constructor only

  • access: Public constructor

  • oracle: No oracle dependencies

constructor() ;

initialize

Initialize the AaveVault 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 _aaveProvider,
    address _rewardsController,
    address _yieldShift,
    address _timelock,
    address _treasury
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress of the admin role
_usdcaddressAddress of the USDC token contract
_aaveProvideraddressAddress of the Aave pool addresses provider
_rewardsControlleraddressAddress of the Aave rewards controller
_yieldShiftaddressAddress of the yield shift contract
_timelockaddressAddress of the timelock contract
_treasuryaddressAddress of the treasury

deployToAave

Deploy USDC to Aave V3 pool to earn yield

Supplies USDC to Aave protocol and receives aUSDC tokens representing the deposit

Notes:

  • security: Validates oracle price freshness, enforces exposure limits and health checks

  • validation: Validates amount > 0, checks max exposure limits, verifies Aave pool health

  • state-changes: Updates principalDeposited, transfers USDC from caller, receives aUSDC

  • events: Emits DeployedToAave with operation details

  • errors: Throws WouldExceedLimit if exceeds maxAaveExposure, AavePoolNotHealthy if pool unhealthy

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to VAULT_MANAGER_ROLE

  • oracle: Requires fresh EUR/USD price for health validation

function deployToAave(uint256 amount) public nonReentrant whenNotPaused 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 protocol, validates slippage and updates principal tracking

Notes:

  • security: Validates withdrawal constraints, enforces minimum balance requirements

  • validation: Validates amount > 0, checks sufficient aUSDC balance, validates slippage

  • state-changes: Updates principalDeposited, withdraws aUSDC, receives USDC

  • events: Emits WithdrawnFromAave with withdrawal details

  • errors: Throws InsufficientBalance if not enough aUSDC, WouldBreachMinimum if below threshold

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to VAULT_MANAGER_ROLE

  • oracle: No oracle dependency for withdrawals

function withdrawFromAave(uint256 amount) public nonReentrant returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
amountuint256Amount of aUSDC to withdraw (6 decimals, use type(uint256).max for all)

Returns

NameTypeDescription
usdcWithdrawnuint256Amount of USDC actually withdrawn (6 decimals)

_validateAndCalculateWithdrawAmount

Validates and calculates the actual withdrawal amount

Internal function to validate withdrawal parameters and calculate actual amount

Notes:

  • security: Validates sufficient balance and handles max withdrawal requests

  • validation: Validates aaveBalance > 0, amount <= aaveBalance

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InsufficientBalance if balance too low

  • reentrancy: Not applicable - pure function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _validateAndCalculateWithdrawAmount(uint256 amount, uint256 aaveBalance)
    internal
    pure
    returns (uint256 withdrawAmount);

Parameters

NameTypeDescription
amountuint256Requested withdrawal amount (6 decimals)
aaveBalanceuint256Current aUSDC balance (6 decimals)

Returns

NameTypeDescription
withdrawAmountuint256Actual amount to withdraw (6 decimals)

_validateWithdrawalConstraints

Validates withdrawal constraints (emergency mode, minimum balance)

Internal function to validate withdrawal constraints and minimum balance requirements

Notes:

  • security: Enforces minimum balance requirements unless in emergency mode

  • validation: Validates remaining balance >= minimum threshold

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Throws WouldBreachMinimum if below minimum balance threshold

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _validateWithdrawalConstraints(uint256 withdrawAmount, uint256 aaveBalance) internal view;

Parameters

NameTypeDescription
withdrawAmountuint256Amount to withdraw (6 decimals)
aaveBalanceuint256Current aUSDC balance (6 decimals)

_validateExpectedWithdrawal

Validates expected withdrawal amounts before external call

Validates expected withdrawal amounts before external 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function _validateExpectedWithdrawal(uint256 withdrawAmount) internal view;

Parameters

NameTypeDescription
withdrawAmountuint256Amount to withdraw

_executeAaveWithdrawal

Executes the Aave withdrawal with proper error handling

Executes the Aave withdrawal with proper error handling

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 _executeAaveWithdrawal(uint256 originalAmount, uint256 withdrawAmount, uint256 usdcBefore)
    internal
    returns (uint256 usdcWithdrawn);

Parameters

NameTypeDescription
originalAmountuint256Original amount requested
withdrawAmountuint256Amount to withdraw from Aave
usdcBeforeuint256USDC balance before withdrawal

Returns

NameTypeDescription
usdcWithdrawnuint256Actual amount withdrawn

_validateWithdrawalResult

Validates the withdrawal result and slippage

Validates the withdrawal result and slippage

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 _validateWithdrawalResult(
    uint256 originalAmount,
    uint256 withdrawAmount,
    uint256 usdcBefore,
    uint256 usdcWithdrawn
) internal view;

Parameters

NameTypeDescription
originalAmountuint256Original amount requested
withdrawAmountuint256Amount to withdraw from Aave
usdcBeforeuint256USDC balance before withdrawal
usdcWithdrawnuint256Actual amount withdrawn

claimAaveRewards

Claim Aave rewards (if any)

Claims any available Aave protocol rewards for the vault's aUSDC position

Notes:

  • security: No additional security checks required - Aave handles reward validation

  • validation: No input validation required - view function checks pending rewards

  • state-changes: Claims rewards to vault address, updates reward tracking

  • events: Emits AaveRewardsClaimed with reward details

  • errors: No errors thrown - safe to call even with no rewards

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to VAULT_MANAGER_ROLE

  • oracle: No oracle dependency for reward claims

function claimAaveRewards() external nonReentrant returns (uint256 rewardsClaimed);

Returns

NameTypeDescription
rewardsClaimeduint256Claimed reward amount (18 decimals)

harvestAaveYield

Harvest Aave yield and distribute via YieldShift

Harvests available yield from Aave lending, charges protocol fees, distributes net yield

Notes:

  • security: Uses CEI pattern, validates slippage, enforces harvest threshold

  • validation: Validates available yield >= harvestThreshold before harvesting

  • state-changes: Updates lastHarvestTime, totalFeesCollected, totalYieldHarvested

  • events: Emits AaveYieldHarvested with harvest details

  • errors: Throws BelowThreshold if yield < harvestThreshold, ExcessiveSlippage if slippage too high

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to VAULT_MANAGER_ROLE

  • oracle: No oracle dependency for yield harvesting

function harvestAaveYield() public nonReentrant returns (uint256 yieldHarvested);

Returns

NameTypeDescription
yieldHarvesteduint256Amount harvested (6 decimals)

getAvailableYield

Returns the total available yield from Aave lending

Calculates yield based on current aToken balance vs principal 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getAvailableYield() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The amount of yield available for distribution

getYieldDistribution

Returns the breakdown of yield distribution between users and protocol

Shows how yield is allocated according to current distribution 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getYieldDistribution()
    external
    view
    returns (uint256 protocolYield, uint256 userYield, uint256 hedgerYield);

Returns

NameTypeDescription
protocolYielduint256Amount of yield allocated to protocol fees
userYielduint256Amount of yield allocated to users
hedgerYielduint256Amount of yield allocated to hedgers

getAaveBalance

Returns the current balance of aTokens held by this vault

Represents the total amount deposited in Aave plus accrued interest

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getAaveBalance() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The current aToken balance

depositUnderlying

Generic external vault adapter deposit entrypoint.

Delegates to deployToAave using adapter-standard semantics for QuantillonVault.

Notes:

  • security: Callable by configured integration flows; underlying logic validates amount and roles.

  • validation: Reverts on zero amount, invalid state, or failed Aave interaction in delegate path.

  • state-changes: Updates principal tracking and deploys USDC to Aave via delegated function.

  • events: Emits deployment/yield-related events from delegated function.

  • errors: Propagates validation, transfer, and Aave interaction errors from delegated function.

  • reentrancy: Reentrancy protections are enforced by delegated function flow.

  • access: Access control is enforced by delegated function flow.

  • oracle: No direct oracle dependency in this wrapper.

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

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).

Returns

NameTypeDescription
sharesReceiveduint256Amount of adapter shares/units received.

withdrawUnderlying

Generic external vault adapter withdraw entrypoint.

Delegates to withdrawFromAave and returns actual USDC withdrawn.

Notes:

  • security: Callable by configured integration flows; delegated function enforces safety checks.

  • validation: Reverts on invalid amount/balance or failed Aave withdrawal in delegate path.

  • state-changes: Updates principal tracking and vault balances through delegated function.

  • events: Emits withdrawal-related events from delegated function.

  • errors: Propagates delegated function errors for validation and Aave failures.

  • reentrancy: Reentrancy protections are enforced by delegated function flow.

  • access: Access control is enforced by delegated function flow.

  • oracle: No direct oracle dependency in this wrapper.

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

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to withdraw (6 decimals).

Returns

NameTypeDescription
usdcWithdrawnuint256Actual USDC withdrawn.

harvestYield

Generic external vault adapter harvest entrypoint.

Delegates to harvestAaveYield to realize and route harvested yield.

Notes:

  • security: Delegated function enforces configured role and dependency checks.

  • validation: Reverts when harvesting preconditions fail in delegated function.

  • state-changes: Realizes Aave yield and updates accounting in delegated function.

  • events: Emits harvest/yield distribution events from delegated function.

  • errors: Propagates delegated function errors.

  • reentrancy: Reentrancy protections are enforced by delegated function flow.

  • access: Access control is enforced by delegated function flow.

  • oracle: No direct oracle dependency in this wrapper.

function harvestYield() external override returns (uint256 harvestedYield);

Returns

NameTypeDescription
harvestedYielduint256Net yield harvested in USDC (6 decimals).

totalUnderlying

Returns total underlying balance for adapter-generic reads.

Mirrors getAaveBalance for adapter-standard interface compatibility.

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 dependency.

function totalUnderlying() external view override returns (uint256 underlyingBalance);

Returns

NameTypeDescription
underlyingBalanceuint256Aave-side USDC-equivalent balance (principal + accrued yield).

getAccruedInterest

Returns the total interest accrued from Aave lending

Calculates interest as current balance minus principal 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getAccruedInterest() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The amount of interest accrued

getAaveAPY

Returns the current APY offered by Aave for the deposited asset

Fetches the supply rate from Aave's reserve 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getAaveAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The current APY in basis points

getAavePositionDetails

Returns detailed information about the Aave position

Provides comprehensive data about the vault's Aave lending position

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getAavePositionDetails()
    external
    view
    returns (uint256 principalDeposited_, uint256 currentBalance, uint256 aTokenBalance, uint256 lastUpdateTime);

Returns

NameTypeDescription
principalDeposited_uint256Total amount originally deposited
currentBalanceuint256Current aToken balance including interest
aTokenBalanceuint256Current aToken balance
lastUpdateTimeuint256Timestamp of last position update

getAaveMarketData

Returns current Aave market data for the deposited asset

Fetches real-time market information from Aave protocol

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getAaveMarketData()
    external
    view
    returns (uint256 supplyRate, uint256 utilizationRate, uint256 totalSupply, uint256 availableLiquidity);

Returns

NameTypeDescription
supplyRateuint256Current supply rate for the asset
utilizationRateuint256Current utilization rate of the reserve
totalSupplyuint256Total supply of the underlying asset
availableLiquidityuint256Available liquidity in the reserve

checkAaveHealth

Performs health checks on the Aave position

Validates that the Aave position is healthy and functioning properly

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 checkAaveHealth() external view returns (bool isHealthy, bool pauseStatus, uint256 lastUpdate);

Returns

NameTypeDescription
isHealthyboolTrue if position is healthy, false if issues detected
pauseStatusboolCurrent pause status of the contract
lastUpdateuint256Timestamp of last health check update

_isAaveHealthy

Check if Aave protocol is healthy

Checks if Aave protocol is functioning properly by verifying reserve data

Notes:

  • security: Uses try-catch to handle potential failures gracefully

  • validation: No input validation required

  • state-changes: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - uses try-catch

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _isAaveHealthy() internal view returns (bool);

Returns

NameTypeDescription
<none>boolbool True if Aave is healthy, false otherwise

autoRebalance

Automatically rebalance the vault allocation

Rebalances the vault allocation based on optimal allocation 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function autoRebalance() external returns (bool rebalanced, uint256 newAllocation, uint256 expectedYield);

Returns

NameTypeDescription
rebalancedboolTrue if rebalancing occurred, false otherwise
newAllocationuint256New allocation percentage after rebalancing
expectedYielduint256Expected yield from the new allocation

calculateOptimalAllocation

Calculates the optimal allocation of funds to Aave

Determines best allocation strategy 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function calculateOptimalAllocation() external view returns (uint256 optimalAllocation, uint256 expectedYield);

Returns

NameTypeDescription
optimalAllocationuint256Recommended amount to allocate to Aave
expectedYielduint256Expected yield from the recommended allocation

setMaxAaveExposure

Sets the maximum exposure limit for Aave deposits

Governance function to control risk by limiting Aave exposure

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 setMaxAaveExposure(uint256 _maxExposure) external;

Parameters

NameTypeDescription
_maxExposureuint256Maximum amount that can be deposited to Aave

emergencyWithdrawFromAave

Emergency withdrawal from Aave protocol

Emergency function to withdraw all funds from Aave protocol

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 emergencyWithdrawFromAave() external nonReentrant returns (uint256 amountWithdrawn);

Returns

NameTypeDescription
amountWithdrawnuint256Amount of USDC withdrawn from Aave

getRiskMetrics

Returns comprehensive risk metrics for the Aave position

Provides detailed risk analysis including concentration and volatility 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getRiskMetrics()
    external
    view
    returns (uint256 exposureRatio, uint256 concentrationRisk, uint256 liquidityRisk);

Returns

NameTypeDescription
exposureRatiouint256Percentage of total assets exposed to Aave
concentrationRiskuint256Risk level due to concentration in Aave (1-3 scale)
liquidityRiskuint256Risk level based on Aave liquidity conditions (1-3 scale)

updateAaveParameters

Update Aave parameters

Updates 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateAaveParameters(uint256 newHarvestThreshold, uint256 newYieldFee, uint256 newRebalanceThreshold)
    external;

Parameters

NameTypeDescription
newHarvestThresholduint256New harvest threshold in USDC
newYieldFeeuint256New yield fee in basis points
newRebalanceThresholduint256New rebalance threshold in basis points

updateYieldShift

Updates the YieldShift contract reference.

Governance-only setter used to rotate the YieldShift dependency for harvested-yield routing.

Notes:

  • security: Restricted to governance and validates non-zero dependency address.

  • validation: Reverts if newYieldShift is zero address.

  • state-changes: Updates yieldShift reference.

  • events: Emits AaveParameterUpdated with old/new encoded addresses.

  • errors: Reverts on unauthorized access or invalid address.

  • reentrancy: No token transfer side effects; single storage write after validation.

  • access: Restricted to governance through AccessControlLibrary.onlyGovernance.

  • oracle: No oracle dependencies.

function updateYieldShift(address newYieldShift) external;

Parameters

NameTypeDescription
newYieldShiftaddressNew YieldShift contract address.

setYieldVaultId

Sets the vault id used when routing harvested yield via YieldShift.

Governance-only setter for destination vault id used by downstream YieldShift calls.

Notes:

  • security: Restricted to governance and prevents unset/invalid id value.

  • validation: Reverts if newYieldVaultId is zero.

  • state-changes: Updates yieldVaultId.

  • events: Emits AaveParameterUpdated with old/new vault id.

  • errors: Reverts on unauthorized access or invalid vault id.

  • reentrancy: No external calls after validation except event emission.

  • access: Restricted to governance through AccessControlLibrary.onlyGovernance.

  • oracle: No oracle dependencies.

function setYieldVaultId(uint256 newYieldVaultId) external;

Parameters

NameTypeDescription
newYieldVaultIduint256Target vault id in stQEUROFactory.

getAaveConfig

Returns the current Aave integration configuration

Provides access to all configuration parameters for Aave integration

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getAaveConfig()
    external
    view
    returns (address aavePool_, address aUSDC_, uint256 harvestThreshold_, uint256 yieldFee_, uint256 maxExposure_);

Returns

NameTypeDescription
aavePool_addressAddress of the Aave pool contract
aUSDC_addressAddress of the aUSDC token contract
harvestThreshold_uint256Minimum yield threshold for harvesting
yieldFee_uint256Fee percentage charged on yield
maxExposure_uint256Maximum allowed exposure to Aave

toggleEmergencyMode

Toggles emergency mode for the Aave vault

Emergency function to enable/disable emergency mode 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function toggleEmergencyMode(bool enabled, string calldata reason) external;

Parameters

NameTypeDescription
enabledboolWhether to enable or disable emergency mode
reasonstringHuman-readable reason for the change

pause

Pauses all Aave vault operations

Emergency function to halt all vault 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function pause() external;

unpause

Unpauses Aave vault operations

Resumes normal vault 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unpause() external;

recoverToken

Recovers accidentally sent ERC20 tokens from the vault

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 vault

Emergency function to recover ETH that shouldn't be in 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external;

Events

DeployedToAave

OPTIMIZED: Indexed operation type for efficient filtering

event DeployedToAave(string indexed operationType, uint256 amount, uint256 aTokensReceived, uint256 newBalance);

WithdrawnFromAave

event WithdrawnFromAave(
    string indexed operationType, uint256 amountRequested, uint256 amountWithdrawn, uint256 newBalance
);

AaveYieldHarvested

event AaveYieldHarvested(string indexed harvestType, uint256 yieldHarvested, uint256 protocolFee, uint256 netYield);

AaveRewardsClaimed

event AaveRewardsClaimed(address indexed rewardToken, uint256 rewardAmount, address recipient);

PositionRebalanced

OPTIMIZED: Indexed reason and parameter for efficient filtering

event PositionRebalanced(string indexed reason, uint256 oldAllocation, uint256 newAllocation);

AaveParameterUpdated

event AaveParameterUpdated(string indexed parameter, uint256 oldValue, uint256 newValue);

EmergencyWithdrawal

event EmergencyWithdrawal(string indexed reason, uint256 amountWithdrawn, uint256 timestamp);

EmergencyModeToggled

event EmergencyModeToggled(string indexed reason, bool enabled);

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.

State Variables

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

morphoVault

IMockMorphoVault public morphoVault

yieldShift

IYieldShift public yieldShift

yieldVaultId

uint256 public yieldVaultId

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 and vault id.

  • validation: Reverts on zero address or zero yieldVaultId_.

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

  • events: No events emitted by constructor.

  • errors: Reverts with ZeroAddress or InvalidVault on invalid inputs.

  • reentrancy: Not applicable - constructor only.

  • access: Public constructor.

  • oracle: No oracle dependencies.

constructor(address admin, address usdc_, address morphoVault_, address yieldShift_, uint256 yieldVaultId_) ;

Parameters

NameTypeDescription
adminaddressAdmin address granted governance and manager roles.
usdc_addressUSDC token address.
morphoVault_addressMock Morpho vault address.
yieldShift_addressYieldShift contract address.
yieldVaultId_uint256YieldShift vault id used when routing harvested yield.

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.

harvestYield

Harvests accrued yield from Morpho and routes it to YieldShift.

Withdraws only the amount above tracked principal, then forwards to YieldShift.

Notes:

  • security: Restricted to VAULT_MANAGER_ROLE; protected by nonReentrant.

  • validation: Reverts only on downstream failures; returns zero when no yield is available.

  • state-changes: Leaves principal unchanged and routes yield through YieldShift.

  • events: Emits downstream transfer/yield events from dependencies.

  • errors: Reverts on downstream withdrawal, approval, or addYield failures.

  • reentrancy: Protected by nonReentrant.

  • access: Restricted to vault manager role.

  • oracle: No oracle dependencies.

function harvestYield()
    external
    override
    onlyRole(VAULT_MANAGER_ROLE)
    nonReentrant
    returns (uint256 harvestedYield);

Returns

NameTypeDescription
harvestedYielduint256USDC yield harvested and routed (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.

setYieldShift

Updates YieldShift destination contract.

Governance maintenance hook for yield routing dependency changes.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts on zero address input.

  • state-changes: Updates yieldShift dependency pointer.

  • events: Emits YieldShiftUpdated.

  • errors: Reverts with ZeroAddress for invalid input.

  • reentrancy: No external calls after state change.

  • access: Restricted to governance role.

  • oracle: No oracle dependencies.

function setYieldShift(address newYieldShift) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newYieldShiftaddressNew YieldShift contract address.

setYieldVaultId

Updates destination vault id used when routing harvested yield.

Governance maintenance hook aligning adapter output with YieldShift vault mapping.

Notes:

  • security: Restricted to GOVERNANCE_ROLE.

  • validation: Reverts when newYieldVaultId is zero.

  • state-changes: Updates yieldVaultId.

  • events: Emits YieldVaultIdUpdated.

  • errors: Reverts with InvalidVault for zero id.

  • reentrancy: No external calls after state change.

  • access: Restricted to governance role.

  • oracle: No oracle dependencies.

function setYieldVaultId(uint256 newYieldVaultId) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
newYieldVaultIduint256New YieldShift vault id.

Events

MorphoVaultUpdated

event MorphoVaultUpdated(address indexed oldVault, address indexed newVault);

YieldShiftUpdated

event YieldShiftUpdated(address indexed oldYieldShift, address indexed newYieldShift);

YieldVaultIdUpdated

event YieldVaultIdUpdated(uint256 indexed oldVaultId, uint256 indexed newVaultId);

Contents

YieldShift

Git Source

Inherits: Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, PausableUpgradeable, SecureUpgradeable

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

State Variables

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")

usdc

IERC20 public usdc

userPool

IUserPool public userPool

hedgerPool

IHedgerPool public hedgerPool

aaveVault

IAaveVault public aaveVault

stQEUROFactory

IStQEUROFactory public stQEUROFactory

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

baseYieldShift

uint256 public baseYieldShift

maxYieldShift

uint256 public maxYieldShift

adjustmentSpeed

uint256 public adjustmentSpeed

targetPoolRatio

uint256 public targetPoolRatio

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

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

MAX_HISTORY_LENGTH

uint256 public constant MAX_HISTORY_LENGTH = 1000

yieldShiftHistory

YieldShiftSnapshot[] public yieldShiftHistory

sourceToVaultId

mapping(address => uint256) public sourceToVaultId

enforceSourceVaultBinding

bool public enforceSourceVaultBinding

Functions

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 _aaveVault,
    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
_aaveVaultaddressAddress 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: Requires fresh oracle price data

function updateYieldDistribution() external nonReentrant whenNotPaused;

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

claimUserYield

Claim user yield

Claims yield for a user after holding period requirements are met

Notes:

  • security: Validates caller is authorized and holding period is met

  • validation: Validates user has pending yield and meets holding period

  • state-changes: Updates user pending yield and transfers USDC

  • events: Emits YieldClaimed event

  • errors: Throws if caller is unauthorized or holding period not met

  • reentrancy: Protected by nonReentrant modifier

  • access: Restricted to user or user pool

  • oracle: No oracle dependencies

function claimUserYield(address user) external nonReentrant returns (uint256 yieldAmount);

Parameters

NameTypeDescription
useraddressAddress of the user to claim yield for

Returns

NameTypeDescription
yieldAmountuint256Amount of yield claimed

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 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: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 _getEligiblePoolMetrics()
    internal
    view
    returns (uint256 userPoolSize, uint256 hedgerPoolSize, uint256 poolRatio);

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

_calculateHoldingPeriodDiscount

Calculate holding period discount based on recent deposit activity

Returns a percentage (in basis points) representing eligible 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function _calculateHoldingPeriodDiscount() internal view returns (uint256 discountBps);

Returns

NameTypeDescription
discountBpsuint256Discount in basis points (10000 = 100%)

_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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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, aaveVault, stQEUROFactory and treasury references in a single governance transaction.

Notes:

  • security: Only governance may call; validates all addresses are non-zero and sane.

  • validation: Uses AccessControlLibrary / YieldValidationLibrary to check addresses.

  • state-changes: Updates userPool, hedgerPool, aaveVault, 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. - aaveVault: AaveVault 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function forceUpdateYieldDistribution() external;

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function _recordPoolSnapshot() internal;

_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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function _addToPoolHistory(PoolSnapshot[] storage poolHistory, uint256 poolSize, bool isUserPool) 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

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external;

Events

YieldDistributionUpdated

OPTIMIZED: Indexed timestamp for efficient time-based filtering

event YieldDistributionUpdated(
    uint256 newYieldShift, uint256 userYieldAllocation, uint256 hedgerYieldAllocation, uint256 indexed timestamp
);

UserYieldClaimed

event UserYieldClaimed(address indexed user, uint256 yieldAmount, uint256 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 aaveVault;
    address stQEUROFactory;
    address treasury;
}

FeeCollector

Git Source

Inherits: AccessControlUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable, UUPSUpgradeable

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

State Variables

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

MED-3: 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")

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

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;

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 and non-contract

  • 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

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 (they owe QEURO to users). When EUR/USD price rises, hedgers lose.

  1. TOTAL UNREALIZED P&L (mark-to-market of current position): totalUnrealizedPnL = FilledVolume - (QEUROBacked × OraclePrice / 1e30)
  2. NET UNREALIZED P&L (used when margin already reflects realized P&L): netUnrealizedPnL = totalUnrealizedPnL - realizedPnL
  3. EFFECTIVE MARGIN (true economic value): effectiveMargin = margin + netUnrealizedPnL
  4. REALIZED P&L (during partial redemptions): When users redeem QEURO, a portion of net unrealized P&L is realized. realizedDelta = (qeuroAmount / qeuroBacked) × netUnrealizedPnL
  • If positive (profit): margin increases
  • If negative (loss): margin decreases
  1. LIQUIDATION MODE (CR ≤ 101%): In liquidation mode, unrealizedPnL = -margin (all margin at risk). effectiveMargin = 0, hedger absorbs pro-rata losses on redemptions.

Note: security-contact: team@quantillon.money

State Variables

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

usdc

IERC20 public usdc

oracle

IOracle public oracle

yieldShift

IYieldShift public yieldShift

vault

IQuantillonVault public vault

treasury

address public treasury

TIME_PROVIDER

TimeProvider public immutable TIME_PROVIDER

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

INFO-2: 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

MED-6: 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

MAX_REWARD_FEE_SPLIT

Maximum allowed value for rewardFeeSplit

uint256 public constant MAX_REWARD_FEE_SPLIT = 1e18

SINGLE_HEDGER_ROTATION_DELAY

Delay before rotating the single hedger after proposal

uint256 public constant SINGLE_HEDGER_ROTATION_DELAY = 24 hours

pendingSingleHedger

Pending single-hedger address awaiting delayed activation

address public pendingSingleHedger

singleHedgerPendingAt

Earliest timestamp at which pendingSingleHedger can be applied (0 = none pending)

uint256 public 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

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

uint256 public constant DEFAULT_MIN_MARGIN_RATIO_BPS = 500

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

Functions

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

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

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)

_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 flashLoanProtection modifier

  • 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)

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 flashLoanProtection modifier

  • 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: Emits HedgingRewardsClaimed with reward details

  • 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

_accrueAndExtractInterestRewards

Accrues interest-differential rewards and extracts claimable amount

Updates pending rewards and reward timestamp using protocol-wide exposure and configured rate differential.

Notes:

  • security: Internal accounting helper; callable only through contract execution flow

  • validation: Handles legacy block-based timestamps by migrating to protocol time

  • state-changes: Updates rewardState.pendingRewards, rewardState.lastRewardClaim, and hedgerLastRewardBlock

  • events: None

  • errors: Arithmetic/validation errors from underlying helpers may revert

  • reentrancy: No external calls

  • access: Internal function

  • oracle: No oracle dependencies

function _accrueAndExtractInterestRewards(address hedger, HedgerRewardState storage rewardState)
    internal
    returns (uint256 interestDifferential);

Parameters

NameTypeDescription
hedgeraddressHedger whose reward accounting is being updated
rewardStateHedgerRewardStateStorage pointer for the hedger reward state

Returns

NameTypeDescription
interestDifferentialuint256Amount claimable from accrued interest differential for this claim cycle

_claimYieldShiftRewards

Claims YieldShift-distributed rewards for a hedger

Reads pending amount and claims once through yieldShift when non-zero.

Notes:

  • security: Relies on trusted yieldShift integration and validates non-zero claimed amount

  • validation: Reverts when claim reports success with zero claimed amount

  • state-changes: May update external YieldShift accounting/state

  • events: No direct events emitted here (caller emits aggregate reward event)

  • errors: Reverts with YieldClaimFailed if claim returns zero amount

  • reentrancy: Performs external calls; used from nonReentrant parent flow

  • access: Internal function

  • oracle: No oracle dependencies

function _claimYieldShiftRewards(address hedger) internal returns (uint256 yieldShiftRewards);

Parameters

NameTypeDescription
hedgeraddressHedger address claiming rewards

Returns

NameTypeDescription
yieldShiftRewardsuint256Claimed YieldShift reward amount

_settleInterestRewards

Queues interest-differential rewards for pull-based withdrawal

Uses pending withdrawal accounting instead of push transfers.

Notes:

  • security: Avoids push-transfer reentrancy surface by queuing funds

  • validation: No action when interestDifferential == 0

  • state-changes: Increments pendingRewardWithdrawals[hedger]

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal function

  • oracle: No oracle dependencies

function _settleInterestRewards(address hedger, uint256 interestDifferential) internal;

Parameters

NameTypeDescription
hedgeraddressHedger receiving queued rewards
interestDifferentialuint256Interest-differential amount to queue

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: Sets pendingRewardWithdrawals[msg.sender] to zero and transfers the pending USDC amount 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, and InvalidAmount when there is no pending reward; 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. totalUnrealizedPnL = FilledVolume - (QEUROBacked × price / 1e30)
  2. netUnrealizedPnL = totalUnrealizedPnL - realizedPnL (margin already reflects realized P&L, so we use net unrealized to avoid double-counting)
  3. effectiveCollateral = margin + netUnrealizedPnL

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: Requires fresh oracle price 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

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 position details

  • 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

Replaces the previous multi-hedger whitelist model with a single hedger

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates governance role and non-zero hedger address

  • state-changes: Updates singleHedger address

  • events: None

  • errors: Throws ZeroAddress if hedger is zero

  • 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

applySingleHedgerRotation

INFO-2: Applies a previously proposed single-hedger rotation after delay.

Finalizes the delayed rotation configured via setSingleHedger.

Notes:

  • security: Restricted to governance and guarded by pending-state + delay checks.

  • validation: Requires a pending hedger and elapsed SINGLE_HEDGER_ROTATION_DELAY.

  • state-changes: Updates singleHedger and clears pending rotation fields.

  • events: Emits SingleHedgerRotationApplied.

  • errors: Reverts when no pending rotation exists or delay has not elapsed.

  • reentrancy: Not applicable - no external calls.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: No oracle interaction.

function applySingleHedgerRotation() external;

fundRewardReserve

MED-2: 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

_isPositionHealthyForFill

Checks if position is healthy enough for new fills

Validates position has sufficient margin ratio after considering unrealized P&L

Notes:

  • security: Internal function - validates position health

  • validation: Checks effective margin > 0 and margin ratio >= minMarginRatio

  • state-changes: None - view function

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Internal helper only

  • oracle: Uses provided price parameter

function _isPositionHealthyForFill(HedgePosition storage p, uint256 price) internal view returns (bool);

Parameters

NameTypeDescription
pHedgePositionStorage pointer to the position struct
priceuint256Current EUR/USD oracle price (18 decimals)

Returns

NameTypeDescription
<none>boolTrue if position is healthy and can accept new fills

_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

Processes redemption for a single position - calculates realized P&L

Calculates and records realized P&L during QEURO redemption

New formula: RealizedP&L = QEUROQuantitySold * (entryPrice - OracleCurrentPrice) Hedgers are SHORT EUR, so they profit when EUR price decreases

Called by _decreaseFilledVolume for normal (non-liquidation) redemptions P&L Calculation Formula:

  1. totalUnrealizedPnL = filledVolume - (qeuroBacked × price / 1e30)
  2. netUnrealizedPnL = totalUnrealizedPnL - realizedPnL (avoids double-counting since margin already reflects realized P&L)
  3. realizedDelta = (qeuroAmount / qeuroBacked) × netUnrealizedPnL After calculation:
  • If realizedDelta > 0 (profit): margin increases
  • If realizedDelta < 0 (loss): margin decreases
  • realizedPnL accumulates the realized portion

Notes:

  • security: Internal function - calculates and records realized P&L

  • validation: Validates entry price > 0 and qeuroAmount > 0

  • state-changes: Updates pos.realizedPnL and decreases filled volume

  • events: Emits MarginUpdated when realized P&L changes margin

  • errors: None

  • reentrancy: Not applicable - internal function

  • access: Internal helper only

  • oracle: Uses provided price parameter

  • security: Internal function - updates position state and margin

  • validation: Validates share > 0, qeuroAmount > 0, price > 0, qeuroBacked > 0

  • state-changes: Updates pos.realizedPnL, pos.margin, totalMargin, pos.positionSize

  • events: Emits MarginUpdated when realized P&L changes margin

  • errors: None - early returns for invalid states

  • reentrancy: Not applicable - internal function, no external calls

  • access: Internal helper only - called by _decreaseFilledVolume

  • oracle: Uses provided price parameter (must be fresh oracle data)

function _processRedeem(
    uint256 posId,
    HedgePosition storage pos,
    uint256 share,
    uint256 filledBefore,
    uint256 price,
    uint256 qeuroAmount
) internal;

Parameters

NameTypeDescription
posIduint256ID of the position being processed
posHedgePositionStorage pointer to the position struct
shareuint256Amount of USDC exposure being released (6 decimals)
filledBeforeuint256Filled volume before redemption (used for P&L calculation)
priceuint256Current EUR/USD oracle price for redemption (18 decimals)
qeuroAmountuint256QEURO amount being redeemed (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)

_validatePositionClosureSafety

Validates that closing a position won't cause protocol undercollateralization

Checks if protocol remains collateralized after removing this position's margin

Notes:

  • security: Internal function - prevents protocol undercollateralization from position closures

  • validation: Checks vault is set, QEURO supply > 0, protocol is collateralized, and remaining margin > positionMargin

  • state-changes: None - view function

  • events: None

  • errors: Reverts with PositionClosureRestricted if closing would cause undercollateralization

  • reentrancy: Not applicable - view function, no state changes

  • access: Internal - only callable within contract

  • oracle: Not applicable - uses vault's collateralization check

function _validatePositionClosureSafety(uint256 positionMargin) internal view;

Parameters

NameTypeDescription
positionMarginuint256Amount of margin in the position being closed

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);

HedgingRewardsClaimed

event HedgingRewardsClaimed(address indexed hedger, bytes32 packedData);

ETHRecovered

event ETHRecovered(address indexed to, uint256 indexed amount);

RewardReserveFunded

MED-2: Emitted when USDC is deposited into the reward reserve

event RewardReserveFunded(address indexed funder, uint256 amount);

SingleHedgerRotationProposed

event SingleHedgerRotationProposed(
    address indexed currentHedger, address indexed pendingHedger, uint256 activatesAt
);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

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;
    uint96 margin;
    uint96 entryPrice;
    uint32 entryTime;
    uint32 lastUpdateTime;
    int128 unrealizedPnL;
    int128 realizedPnL; // Cumulative realized P&L from closed portions
    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

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

State Variables

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

MINT_FEE_RATE

Protocol fee rate for minting (0.1% = 1e15)

Fee is calculated as: fee = amount * MINT_FEE_RATE / PRECISION

Value: 1e15 = 0.1% (since PRECISION = 1e18 = 100%)

uint256 public constant MINT_FEE_RATE = 1e15

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

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: Protected by 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: Protected by 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 reentrancy guard

  • 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: Protected by 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 reentrancy guard

  • 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

_checkAndUpdateBurnRateLimit

Checks and updates the burn 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.currentHourBurned 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 _checkAndUpdateBurnRateLimit(uint256 amount) internal;

Parameters

NameTypeDescription
amountuint256The amount to be burned (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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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

ProtocolFeeCollected

Emitted when protocol fee is collected on mint

event ProtocolFeeCollected(uint256 indexed amount, uint256 indexed feeAmount, address indexed feeCollector);

Parameters

NameTypeDescription
amountuint256Total amount minted
feeAmountuint256Protocol fee amount collected
feeCollectoraddressAddress of the fee collector

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

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: 4 years
  • 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

State Variables

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

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

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

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

Functions

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

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: Protected by 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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 reentrancy guard

  • 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

_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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

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

State Variables

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")

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

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

INFO-7: 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

INFO-7: 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

MAX_HEDGER_REWARD_FEE_SPLIT

Maximum value allowed for hedgerRewardFeeSplit

uint256 private constant MAX_HEDGER_REWARD_FEE_SPLIT = 1e18

minCollateralizationRatioForMinting

Minimum collateralization ratio required for minting QEURO (in 1e18 precision, NOT basis points)

INFO-7: 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

DEV_MODE_DELAY

MED-1: Minimum delay before a proposed dev-mode change takes effect

uint256 private constant DEV_MODE_DELAY = 48 hours

DEV_MODE_DELAY_BLOCKS

MED-1: Canonical block delay for dev-mode proposals (12s block target)

uint256 private constant DEV_MODE_DELAY_BLOCKS = DEV_MODE_DELAY / 12

pendingDevMode

MED-1: Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

MED-1: Block at which pendingDevMode may be applied (0 = no pending proposal)

uint256 public devModePendingAt

lastPriceUpdateTime

Variable to store the timestamp of the last valid price update

uint256 private lastPriceUpdateTime

Functions

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: Protected by 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.

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 cached state and canMint logic.

function _enforceMintEligibility() internal view;

_enforceMintPriceDeviation

Enforces mint-time EUR/USD deviation guard unless dev mode is enabled.

Compares live price vs cached baseline and reverts when deviation exceeds configured threshold.

Notes:

  • security: Blocks minting 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 _enforceMintPriceDeviation(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
    view
    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.

_enforceProjectedMintCollateralization

Ensures projected collateralization remains above mint threshold after this mint.

Simulates post-mint collateral/supply state and compares to configured minimum ratio.

Notes:

  • security: Prevents minting that would violate collateralization policy.

  • validation: Reverts if projected backing requirement is zero or projected ratio is too low.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: Reverts with InvalidAmount or InsufficientCollateralization.

  • reentrancy: Not applicable for view helper.

  • access: Internal helper.

  • oracle: Uses supplied validated oracle input.

function _enforceProjectedMintCollateralization(uint256 netAmount, uint256 qeuroToMint, uint256 eurUsdPrice)
    internal
    view;

Parameters

NameTypeDescription
netAmountuint256Net USDC that will be added as collateral.
qeuroToMintuint256QEURO amount that will be minted.
eurUsdPriceuint256Validated EUR/USD price used for backing requirement conversion.

_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 AaveVault is set and amount > 0

  • state-changes: Updates totalUsdcHeld and totalUsdcInAave before calling AaveVault

  • 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)
    internal;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to redeem (18 decimals)
minUsdcOutuint256Minimum USDC expected (slippage protection)
collateralizationRatioBpsuint256Current CR in basis points (for event emission)

_redeemLiquidationCommit

Commits liquidation-mode redemption effects/interactions

Called via explicit self-call from _redeemLiquidationMode.

Notes:

  • security: Restricted by onlySelf; 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: External self-call entrypoint only

  • 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.

LOW-3 hardening: 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: Protected by 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: Protected by 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: Validates input parameters and 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 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: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by 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: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by 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: Emits ParametersUpdated event

  • 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.

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.

harvestVaultYield

Harvests yield from a specific external vault adapter.

Governance-triggered wrapper around adapter harvestYield.

Notes:

  • security: Restricted to GOVERNANCE_ROLE; protected by nonReentrant.

  • validation: Reverts when vault id is invalid/inactive or adapter is unset.

  • state-changes: Adapter-side yield state may update; vault emits harvest event.

  • events: Emits ExternalVaultYieldHarvested.

  • errors: Reverts on invalid configuration or adapter harvest failures.

  • reentrancy: Guarded by nonReentrant.

  • access: Governance-only.

  • oracle: No direct oracle dependency.

function harvestVaultYield(uint256 vaultId)
    external
    onlyRole(GOVERNANCE_ROLE)
    nonReentrant
    returns (uint256 harvestedYield);

Parameters

NameTypeDescription
vaultIduint256Vault id whose adapter yield should be harvested.

Returns

NameTypeDescription
harvestedYielduint256Yield harvested by adapter in USDC units.

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 best-effort 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: No explicit errors; adapter read failure is handled via fallback.

  • 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 adapter (fallbacks to principal on read failure).

_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.

_withdrawFromExternalVault

Withdraws up to remaining USDC principal from one external vault id.

Caps withdrawal at locally tracked principal and requires adapter to return exact requested amount.

Notes:

  • security: Internal helper used by controlled redemption liquidity flow.

  • validation: Skips inactive/unconfigured/zero-principal vaults; reverts on adapter mismatch.

  • state-changes: Decreases per-vault and global principal trackers before adapter withdrawal.

  • events: Emits UsdcWithdrawnFromExternalVault on successful withdrawal.

  • errors: Reverts with InvalidAmount if adapter withdrawal result mismatches request.

  • reentrancy: Internal helper; adapter interaction occurs after accounting updates.

  • access: Internal helper.

  • oracle: No oracle dependencies.

function _withdrawFromExternalVault(uint256 vaultId, uint256 remaining) internal returns (uint256 withdrawnAmount);

Parameters

NameTypeDescription
vaultIduint256Vault id to withdraw from.
remaininguint256Remaining aggregate withdrawal amount required.

Returns

NameTypeDescription
withdrawnAmountuint256Amount withdrawn from this vault id (0 when skipped/ineligible).

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Updates the price cache with the current oracle price

Allows governance to manually refresh the price cache to prevent deviation check failures

Useful when price has moved significantly and cache needs to be updated

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 onlyRole(GOVERNANCE_ROLE) 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

_updatePriceTimestamp

Updates the last valid price timestamp when a valid price is fetched

Internal function to track price update timing for monitoring

Notes:

  • security: Updates timestamp only for valid price fetches

  • validation: No input validation required

  • state-changes: Updates lastPriceUpdateTime if price is valid

  • 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 _updatePriceTimestamp(bool isValid) internal;

Parameters

NameTypeDescription
isValidboolWhether the current price fetch was valid

_getExternalVaultCollateralBalance

Computes aggregate external-vault collateral balance including accrued yield.

Reads adapter totalUnderlying values with principal fallback on read failure.

Notes:

  • security: Internal read helper.

  • validation: Uses fallback to tracked principal when adapter reads fail.

  • state-changes: No state changes.

  • events: No events emitted.

  • errors: No explicit errors; read failures are handled via fallback.

  • 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.

_getTotalCollateralWithAccruedYield

Returns total collateral available including held and external-vault balances.

Sum of totalUsdcHeld and _getExternalVaultCollateralBalance().

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

MED-2: 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

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() public view returns (bool);

Returns

NameTypeDescription
<none>boolcanMint Whether minting is currently allowed

initializePriceCache

LOW-4: Pure view variant of getProtocolCollateralizationRatio using cached oracle price.

LOW-5: 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 current collateralization ratio

Returns true if collateralization ratio < criticalCollateralizationRatio

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 liquidation status

  • oracle: No oracle dependencies

function shouldTriggerLiquidation() public view returns (bool shouldLiquidate);

Returns

NameTypeDescription
shouldLiquidateboolWhether liquidation should be triggered

pause

Returns liquidation status and key metrics for pro-rata redemption

Pauses all vault operations

Protocol enters liquidation mode when CR <= 101%. In this mode, users can redeem pro-rata.

When paused:

  • No mint/redeem possible
  • Read functions still active

Notes:

  • security: View function - no state changes

  • validation: No input validation required

  • state-changes: None - view function

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check liquidation status

  • oracle: Requires oracle price for collateral calculation

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

_syncMintWithHedgersOrRevert

Internal helper to notify HedgerPool about user mints.

LOW-5 / INFO-2: 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

Attempts to release hedger fills but swallows failures to avoid blocking users

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: Silently ignores downstream errors

  • 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)

proposeDevMode

Toggles dev mode to disable price caching requirements

MED-1: 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

MED-1: 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%)

HedgerPoolNotificationFailed

LOW-3: Emitted when notifying HedgerPool of a liquidation redemption fails

event HedgerPoolNotificationFailed(uint256 qeuroAmount);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO that was being redeemed

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

CollateralizationStatusChanged

Emitted when protocol collateralization status changes

event CollateralizationStatusChanged(
    uint256 indexed currentRatio, bool indexed canMint, bool indexed shouldLiquidate
);

Parameters

NameTypeDescription
currentRatiouint256Current protocol collateralization ratio (in basis points)
canMintboolWhether minting is currently allowed based on collateralization
shouldLiquidateboolWhether liquidation should be triggered based on collateralization

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

MED-1: 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);

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);

ExternalVaultYieldHarvested

event ExternalVaultYieldHarvested(uint256 indexed vaultId, uint256 harvestedYield);

ExternalVaultDeploymentFailed

event ExternalVaultDeploymentFailed(uint256 indexed vaultId, uint256 amount, bytes reason);

HedgerSyncFailed

event HedgerSyncFailed(string operation, uint256 amount, uint256 price, bytes reason);

UsdcWithdrawnFromExternalVault

event UsdcWithdrawnFromExternalVault(uint256 indexed vaultId, uint256 indexed usdcAmount, uint256 principalInVault);

HedgerRewardFeeSplitUpdated

event HedgerRewardFeeSplitUpdated(uint256 previousSplit, uint256 newSplit);

ProtocolFeeRouted

event ProtocolFeeRouted(string sourceType, uint256 totalFee, uint256 hedgerReserveShare, uint256 collectorShare);

Structs

LiquidationCommitParams

struct LiquidationCommitParams {
    address redeemer;
    uint256 qeuroAmount;
    uint256 totalSupply;
    uint256 usdcPayout;
    uint256 netUsdcPayout;
    uint256 fee;
    uint256 collateralizationRatioBps;
    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

State Variables

UPGRADER_ROLE

Role for upgrade operations

bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE")

timelock

Timelock contract for secure upgrades

ITimelockUpgradeable public timelock

secureUpgradesEnabled

Whether the contract is using secure upgrades

bool public secureUpgradesEnabled

EMERGENCY_DISABLE_DELAY

INFO-4: Minimum delay before a proposed emergency-disable takes effect (24h)

uint256 public constant EMERGENCY_DISABLE_DELAY = 24 hours

EMERGENCY_DISABLE_DELAY_BLOCKS

INFO-4: Canonical block delay for emergency-disable proposals (12s block target)

uint256 public constant EMERGENCY_DISABLE_DELAY_BLOCKS = EMERGENCY_DISABLE_DELAY / 12

EMERGENCY_DISABLE_QUORUM

Emergency-disable approvals required before apply can succeed

uint256 public constant EMERGENCY_DISABLE_QUORUM = 2

emergencyDisablePendingAt

INFO-4: Block at which emergencyDisable can be applied (0 = no pending proposal)

uint256 public emergencyDisablePendingAt

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")

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 from timelock's shared TimeProvider

Falls back to block timestamp only before timelock is configured.

Notes:

  • security: Uses timelock-backed canonical time when available; fallback preserves liveness during bootstrap

  • validation: Validates timelock address and code presence before external call

  • state-changes: None

  • events: None

  • errors: None - failures fall back to block.timestamp

  • reentrancy: Read-only helper; no state mutation

  • access: Internal helper

  • oracle: No oracle dependencies

function _protocolTime() internal view returns (uint256);

__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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function setTimelock(address _timelock) external onlyRole(DEFAULT_ADMIN_ROLE);

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function toggleSecureUpgrades(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
enabledboolWhether to enable secure upgrades

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

INFO-4: 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function proposeEmergencyDisableSecureUpgrades() external onlyRole(DEFAULT_ADMIN_ROLE);

approveEmergencyDisableSecureUpgrades

INFO-4/NEW-3: 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

INFO-4: 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

INFO-4: 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

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

State Variables

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 (LOW-6: 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")

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

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

Functions

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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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; // HIGH-1: proxy contract that initiated this upgrade proposal
    uint256 proposedAt;
    uint256 executableAt;
    uint256 expiryAt; // LOW-6: 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

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

State Variables

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")

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

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

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

BLOCKS_PER_DAY

uint256 public constant BLOCKS_PER_DAY = 7200

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

Functions

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

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: Protected by 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

_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[] calldata minQeuroOuts,
    uint256 /* totalNetAmount */
)
    internal;

Parameters

NameTypeDescription
usdcAmountsuint256[]Array of USDC amounts (6 decimals)
minQeuroOutsuint256[]Array of minimum QEURO outputs (18 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;

claimStakingRewards

Claim staking rewards

This function allows users to claim their pending staking rewards. It calculates and transfers the rewards based on their staked amount.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 claimStakingRewards() external nonReentrant returns (uint256 rewardAmount);

Returns

NameTypeDescription
rewardAmountuint256Amount of QEURO rewards claimed (18 decimals)

batchRewardClaim

Batch claim staking rewards for multiple users (admin function)

This function allows admins to claim rewards for multiple users in one transaction. Useful for protocol-wide reward distributions or automated reward processing.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 batchRewardClaim(address[] calldata users)
    external
    nonReentrant
    onlyRole(GOVERNANCE_ROLE)
    returns (uint256[] memory rewardAmounts);

Parameters

NameTypeDescription
usersaddress[]Array of user addresses to claim rewards for

Returns

NameTypeDescription
rewardAmountsuint256[]Array of reward amounts claimed for each user (18 decimals)

_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)

getTotalStakes

Get the total USDC equivalent withdrawals across all users

Get the total QEURO staked across all users

Used for analytics and cash flow monitoring

Returns the total amount of QEURO currently staked in the pool

Notes:

  • access: Public access

  • oracle: No oracle dependencies

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getTotalStakes() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total withdrawals in USDC equivalent (6 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

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

StakingRewardsClaimed

Emitted when staking rewards are claimed by a user

Indexed parameters allow efficient filtering of events

event StakingRewardsClaimed(address indexed user, uint256 rewardAmount, uint256 timestamp);

Parameters

NameTypeDescription
useraddressAddress of the user who claimed rewards
rewardAmountuint256Amount of QEURO rewards claimed (18 decimals)
timestampuint256Timestamp of the reward claim

YieldDistributed

Emitted when yield is distributed to stakers

OPTIMIZED: Indexed timestamp for efficient time-based filtering

event YieldDistributed(uint256 totalYield, uint256 yieldPerShare, uint256 indexed timestamp);

Parameters

NameTypeDescription
totalYielduint256Total amount of yield distributed (18 decimals)
yieldPerShareuint256Amount of yield per staked QEURO share (18 decimals)
timestampuint256Timestamp of the yield distribution

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

Title: stQEUROFactory

Deploys and registers one stQEURO token proxy per staking vault.

State Variables

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE")

VAULT_FACTORY_ROLE

bytes32 public constant VAULT_FACTORY_ROLE = keccak256("VAULT_FACTORY_ROLE")

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

Functions

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.

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, ERC20Upgradeable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, SecureUpgradeable

Title: stQEUROToken

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Yield-bearing wrapper for QEURO tokens (yield accrual mechanism)

Main characteristics:

  • Yield-bearing wrapper token for QEURO
  • Exchange rate increases over time as yield accrues
  • Similar to stETH (Lido's staked ETH token)
  • Automatic yield distribution to all stQEURO holders
  • Fee structure for protocol sustainability
  • Emergency pause mechanism for crisis situations
  • Upgradeable via UUPS pattern

Staking mechanics:

  • Users stake QEURO to receive stQEURO
  • Exchange rate starts at 1:1 and increases over time
  • Yield is distributed proportionally to all stQEURO holders
  • Users can unstake at any time to receive QEURO + accrued yield
  • No lock-up period or cooldown requirements

Yield distribution:

  • Yield is distributed from protocol fees and yield shift mechanisms
  • Exchange rate increases as yield accrues
  • All stQEURO holders benefit from yield automatically
  • Yield fees charged for protocol sustainability
  • Real-time yield tracking and distribution

Exchange rate mechanism:

  • Exchange rate = (totalUnderlying + totalYieldEarned) / totalSupply
  • Increases over time as yield is earned
  • Updated periodically or when yield is distributed
  • Minimum yield threshold prevents frequent updates
  • Maximum update frequency prevents excessive gas costs

Fee structure:

  • Yield fees on distributed yield
  • Treasury receives fees for protocol sustainability
  • Dynamic fee adjustment based on market conditions
  • Transparent fee structure for users

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 yield distribution mechanisms
  • Exchange rate validation

Integration points:

  • QEURO token for staking and unstaking
  • USDC for yield payments
  • Yield shift mechanism for yield management
  • Treasury for fee collection
  • Vault math library for calculations

Note: security-contact: team@quantillon.money

State Variables

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")

YIELD_MANAGER_ROLE

Role for yield management operations (distribution, updates)

keccak256 hash avoids role collisions with other contracts

Should be assigned to yield management system or governance

bytes32 public constant YIELD_MANAGER_ROLE = keccak256("YIELD_MANAGER_ROLE")

EMERGENCY_ROLE

Role for emergency operations (pause, emergency actions)

keccak256 hash avoids role collisions with other contracts

Should be assigned to emergency multisig

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

qeuro

Role for performing contract upgrades via UUPS pattern

QEURO token contract for staking and unstaking

Used for all QEURO staking and unstaking operations

Should be the official QEURO token contract

IQEUROToken public qeuro

yieldShift

YieldShift contract for yield distribution

Handles yield distribution and management

Used for yield calculations and distributions

IYieldShift public yieldShift

usdc

USDC token for yield payments

Used for yield distributions to stQEURO holders

Should be the official USDC contract on the target network

IERC20 public usdc

treasury

Treasury address for fee collection

Receives yield fees for protocol sustainability

Should be a secure multisig or DAO treasury

address public treasury

oracle

Oracle for EUR/USD price — used to convert USDC yield to QEURO denomination

HIGH-3: required so distributeYield() scales 6-dec USDC yield to 18-dec QEURO exchange rate

IOracle public oracle

yieldConversionPrice

Cached EUR/USD conversion price (18 decimals) used by distributeYield

Updated by governance to avoid external oracle callbacks during yield distribution

uint256 public yieldConversionPrice

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

vaultName

Human-readable vault identifier used to derive token metadata

string public vaultName

exchangeRate

Exchange rate between QEURO and stQEURO (18 decimals)

Increases over time as yield accrues (like stETH)

Formula: (totalUnderlying + totalYieldEarned) / totalSupply

uint256 public exchangeRate

lastUpdateTime

Timestamp of last exchange rate update

Used to track when exchange rate was last updated

Used for yield calculation intervals

uint256 public lastUpdateTime

totalUnderlying

Total QEURO underlying the stQEURO supply

Sum of all QEURO staked by users

Used for exchange rate calculations

uint256 public totalUnderlying

_flashLoanTotalUnderlyingBefore

totalUnderlying before flash loan check (used by flashLoanProtection modifier)

uint256 private _flashLoanTotalUnderlyingBefore

totalYieldEarned

Total yield earned by stQEURO holders

Sum of all yield distributed to stQEURO holders

Used for exchange rate calculations and analytics

uint256 public totalYieldEarned

yieldFee

Fee charged on yield distributions (in basis points)

Example: 200 = 2% yield fee

Revenue source for the protocol

uint256 public yieldFee

minYieldThreshold

Minimum yield amount to trigger exchange rate update

Prevents frequent updates for small yield amounts

Reduces gas costs and improves efficiency

uint256 public minYieldThreshold

maxUpdateFrequency

Maximum time between exchange rate updates (in seconds)

Ensures regular updates even with low yield

Example: 1 day = 86400 seconds

uint256 public maxUpdateFrequency

VIRTUAL_SHARES

Virtual shares to prevent exchange rate manipulation

Prevents donation attacks by maintaining minimum share value

uint256 private constant VIRTUAL_SHARES = 1e8

VIRTUAL_ASSETS

Virtual assets to prevent exchange rate manipulation

Prevents donation attacks by maintaining minimum asset value

uint256 private constant VIRTUAL_ASSETS = 1e8

MAX_BATCH_SIZE

Maximum batch size for staking operations to prevent DoS

Prevents out-of-gas attacks through large arrays

uint256 public constant MAX_BATCH_SIZE = 100

Functions

flashLoanProtection

Modifier to protect against flash loan attacks

Checks that the contract's total underlying QEURO doesn't decrease during execution

This prevents flash loans that would drain QEURO from the contract

modifier flashLoanProtection() ;

_flashLoanProtectionBefore

function _flashLoanProtectionBefore() private;

_flashLoanProtectionAfter

function _flashLoanProtectionAfter() private view;

constructor

Constructor for stQEURO token implementation

Initializes the time provider and disables initialization on implementation

Notes:

  • security: Disables initialization on implementation for security

  • 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

  • oz-upgrades-unsafe-allow: constructor

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderAddress of the time provider contract

initialize

Initialize the stQEURO token 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 ERC20, 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 _qeuro,
    address _yieldShift,
    address _usdc,
    address _treasury,
    address _timelock
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress of the admin role
_qeuroaddressAddress of the QEURO token contract
_yieldShiftaddressAddress of the YieldShift contract
_usdcaddressAddress of the USDC token contract
_treasuryaddressAddress of the treasury
_timelockaddressAddress of the timelock contract

initialize

Initialize the stQEURO token contract with dynamic metadata for a vault.

Uses caller-supplied token name/symbol and vault label, then delegates setup to _initializeStQEURO.

Notes:

  • security: Validates critical addresses and initializes access-controlled roles.

  • validation: Reverts if required addresses are invalid or zero.

  • state-changes: Initializes token metadata, roles, dependencies, and core staking parameters.

  • events: Emits role initialization events from inherited OpenZeppelin modules.

  • errors: Reverts with custom validation errors when initialization inputs are invalid.

  • reentrancy: Protected by initializer; callable once per proxy instance.

  • access: Public initializer for proxy deployment flow.

  • oracle: No direct oracle dependency during initialization.

function initialize(
    address admin,
    address _qeuro,
    address _yieldShift,
    address _usdc,
    address _treasury,
    address _timelock,
    string calldata _vaultName
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress of the admin role
_qeuroaddressAddress of the QEURO token contract
_yieldShiftaddressAddress of the YieldShift contract
_usdcaddressAddress of the USDC token contract
_treasuryaddressAddress of the treasury
_timelockaddressAddress of the timelock contract
_vaultNamestringHuman-readable vault name (e.g. CORE, ALPHA1)

_initializeStQEURODependencies

Internal initializer shared by both public initialization entrypoints.

Performs full dependency validation, role setup, and default parameter bootstrap.

Notes:

  • security: Centralizes initialization checks to keep both entrypoints consistent and hardened.

  • validation: Reverts if required addresses are zero or invalid for configuration.

  • state-changes: Initializes inherited modules, role assignments, dependencies, and default rate parameters.

  • events: Emits inherited initialization/role events as modules are configured.

  • errors: Reverts with custom address/validation errors when config is invalid.

  • reentrancy: Internal initializer path; reached only through initializer-guarded functions.

  • access: Internal helper.

  • oracle: No direct oracle reads during initialization.

function _initializeStQEURODependencies(
    address admin,
    address qeuroAddress,
    address yieldShiftAddress,
    address usdcAddress,
    address treasuryAddress,
    address timelockAddress
) internal;

Parameters

NameTypeDescription
adminaddressAdmin role address
qeuroAddressaddressQEURO token address
yieldShiftAddressaddressYieldShift contract address
usdcAddressaddressUSDC token address
treasuryAddressaddressTreasury address
timelockAddressaddressTimelock address used by SecureUpgradeable

stake

Stake QEURO to receive stQEURO

Converts QEURO to stQEURO at current exchange rate

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 stake(uint256 qeuroAmount)
    external
    nonReentrant
    whenNotPaused
    flashLoanProtection
    returns (uint256 stQEUROAmount);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to stake

Returns

NameTypeDescription
stQEUROAmountuint256Amount of stQEURO received

unstake

Unstake QEURO by burning stQEURO

Burns stQEURO tokens and returns QEURO at current exchange rate

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 unstake(uint256 stQEUROAmount) external nonReentrant whenNotPaused returns (uint256 qeuroAmount);

Parameters

NameTypeDescription
stQEUROAmountuint256Amount of stQEURO to burn

Returns

NameTypeDescription
qeuroAmountuint256Amount of QEURO received

batchStake

Batch stake QEURO to receive stQEURO for multiple amounts

Processes multiple staking operations 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchStake(uint256[] calldata qeuroAmounts)
    external
    nonReentrant
    whenNotPaused
    returns (uint256[] memory stQEUROAmounts);

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts to stake

Returns

NameTypeDescription
stQEUROAmountsuint256[]Array of stQEURO amounts received

batchUnstake

Batch unstake QEURO by burning stQEURO for multiple amounts

Processes multiple unstaking operations 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchUnstake(uint256[] calldata stQEUROAmounts)
    external
    nonReentrant
    whenNotPaused
    returns (uint256[] memory qeuroAmounts);

Parameters

NameTypeDescription
stQEUROAmountsuint256[]Array of stQEURO amounts to burn

Returns

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts received

batchTransfer

Batch transfer stQEURO tokens to multiple addresses

Transfers stQEURO 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Returns

NameTypeDescription
<none>boolbool Always returns true if successful

distributeYield

Distribute yield to stQEURO holders (increases exchange rate)

Distributes USDC yield to stQEURO holders by increasing the exchange rate

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 distributeYield(uint256 yieldAmount) external nonReentrant onlyRole(YIELD_MANAGER_ROLE);

Parameters

NameTypeDescription
yieldAmountuint256Amount of yield in USDC

claimYield

Claim accumulated yield for a user (in USDC)

In yield accrual model, yield is claimed by unstaking - kept for 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function claimYield() public returns (uint256 yieldAmount);

Returns

NameTypeDescription
yieldAmountuint256Amount of yield claimed (always 0 in this model)

getPendingYield

Get pending yield for a user (in USDC)

In yield accrual model, yield is distributed via exchange rate increases

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getPendingYield(address user) public view returns (uint256 yieldAmount);

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
yieldAmountuint256Pending yield amount

getExchangeRate

Get current exchange rate between QEURO and stQEURO

Returns the current exchange rate calculated with yield accrual

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getExchangeRate() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Current exchange rate (18 decimals)

getTVL

Get total value locked in stQEURO

Returns the total amount of QEURO underlying all stQEURO 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getTVL() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total value locked in QEURO (18 decimals)

getQEUROEquivalent

Get user's QEURO equivalent balance

Calculates the QEURO equivalent of a user's stQEURO balance

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getQEUROEquivalent(address user) external view returns (uint256 qeuroEquivalent);

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
qeuroEquivalentuint256QEURO equivalent of stQEURO balance

getStakingStats

Get staking statistics

Returns comprehensive staking statistics including supply, TVL, and 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getStakingStats()
    external
    view
    returns (
        uint256 totalStQEUROSupply,
        uint256 totalQEUROUnderlying,
        uint256 currentExchangeRate,
        uint256 totalYieldEarned_,
        uint256 apy
    );

Returns

NameTypeDescription
totalStQEUROSupplyuint256Total supply of stQEURO tokens
totalQEUROUnderlyinguint256Total QEURO underlying all stQEURO
currentExchangeRateuint256Current exchange rate between QEURO and stQEURO
totalYieldEarned_uint256Total yield earned by all stakers
apyuint256Annual percentage yield (calculated off-chain)

_updateExchangeRate

Update exchange rate based on time elapsed and yield accrual

Internal function to update exchange rate when conditions are met

Notes:

  • security: Calculates new rate with bounds checking to prevent manipulation

  • validation: No input validation required

  • state-changes: Updates exchangeRate and lastUpdateTime if rate changes

  • events: Emits ExchangeRateUpdated if rate changes

  • errors: No errors thrown - safe arithmetic used

  • reentrancy: Not protected - internal function only

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function _updateExchangeRate() internal;

_calculateCurrentExchangeRate

Calculate current exchange rate including accrued yield

Returns the stored exchange rate which is updated via distributeYield()

Notes:

  • security: Uses minimum supply threshold to prevent manipulation

  • validation: No input validation required

  • 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 _calculateCurrentExchangeRate() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current exchange rate (18 decimals) including pending yield

updateYieldParameters

Update yield parameters

Updates yield fee, minimum threshold, and maximum update frequency

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 updateYieldParameters(uint256 _yieldFee, uint256 _minYieldThreshold, uint256 _maxUpdateFrequency)
    external
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_yieldFeeuint256New yield fee in basis points
_minYieldThresholduint256New minimum yield threshold in USDC
_maxUpdateFrequencyuint256New maximum update frequency in seconds

updateTreasury

Update treasury address

Updates the treasury address for token recovery 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateTreasury(address _treasury) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

setOracle

Sets the oracle used to price USDC yield in QEURO terms.

HIGH-3: Required so distributeYield() can convert USDC (6 decimals) to QEURO (18 decimals) using a EUR/USD price feed. Without a valid oracle, yield distribution reverts.

Notes:

  • security: Ensures _oracle is a non-zero address to avoid bricking yield distribution.

  • validation: Reverts with ZeroAddress if _oracle equals address(0).

  • state-changes: Updates the oracle contract reference used by distributeYield().

  • events: None.

  • errors: ZeroAddress if _oracle is the zero address.

  • reentrancy: Not applicable – no external calls after state change.

  • access: Restricted to GOVERNANCE_ROLE.

  • oracle: Configures the external EUR/USD oracle used for USDC→QEURO conversion.

function setOracle(address _oracle) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_oracleaddressAddress of the IOracle implementation (typically OracleRouter).

updateYieldConversionPrice

Updates the cached EUR/USD conversion price used in yield distribution.

Governance maintenance hook for manually refreshing conversion cache used by yield accounting.

Notes:

  • security: Restricted to GOVERNANCE_ROLE

  • validation: Reverts when eurUsdPrice == 0

  • state-changes: Updates yieldConversionPrice

  • events: Emits YieldConversionPriceUpdated

  • errors: Reverts with InvalidOraclePrice when input is zero

  • reentrancy: No external calls

  • access: Governance-only external function

  • oracle: Uses governance-supplied oracle-derived price input

function updateYieldConversionPrice(uint256 eurUsdPrice) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
eurUsdPriceuint256New EUR/USD price in 18 decimals.

decimals

Returns the number of decimals used by the token

Always returns 18 to match QEURO token standard

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 decimals() public pure override returns (uint8);

Returns

NameTypeDescription
<none>uint8The number of decimals (18)

pause

Pauses all token transfers and minting/burning operations

Can only be called by addresses with EMERGENCY_ROLE during emergencies

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 pause() external onlyRole(EMERGENCY_ROLE);

unpause

Unpauses all token transfers and minting/burning operations

Can only be called by addresses with EMERGENCY_ROLE to resume 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unpause() external onlyRole(EMERGENCY_ROLE);

emergencyWithdraw

Emergency withdrawal of QEURO (only in emergency)

Emergency function to withdraw QEURO for a specific 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function emergencyWithdraw(address user) external onlyRole(EMERGENCY_ROLE);

Parameters

NameTypeDescription
useraddressAddress of the user to withdraw for

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external onlyRole(DEFAULT_ADMIN_ROLE);

getVirtualProtectionStatus

Returns the current virtual protection status

Useful for monitoring and debugging virtual 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 getVirtualProtectionStatus()
    external
    view
    returns (uint256 virtualShares, uint256 virtualAssets, uint256 effectiveSupply, uint256 effectiveAssets);

Returns

NameTypeDescription
virtualSharesuint256Current virtual shares amount
virtualAssetsuint256Current virtual assets amount
effectiveSupplyuint256Effective supply including virtual shares
effectiveAssetsuint256Effective assets including virtual assets

Events

QEUROStaked

Emitted when QEURO is staked to receive stQEURO

Indexed parameters allow efficient filtering of events

event QEUROStaked(address indexed user, uint256 qeuroAmount, uint256 stQEUROAmount);

Parameters

NameTypeDescription
useraddressAddress of the user who staked
qeuroAmountuint256Amount of QEURO staked (18 decimals)
stQEUROAmountuint256Amount of stQEURO received (18 decimals)

QEUROUnstaked

Emitted when stQEURO is unstaked to receive QEURO

Indexed parameters allow efficient filtering of events

event QEUROUnstaked(address indexed user, uint256 stQEUROAmount, uint256 qeuroAmount);

Parameters

NameTypeDescription
useraddressAddress of the user who unstaked
stQEUROAmountuint256Amount of stQEURO burned (18 decimals)
qeuroAmountuint256Amount of QEURO received (18 decimals)

ExchangeRateUpdated

Emitted when exchange rate is updated

Used to track exchange rate changes over time

event ExchangeRateUpdated(uint256 oldRate, uint256 newRate, uint256 timestamp);

Parameters

NameTypeDescription
oldRateuint256Previous exchange rate (18 decimals)
newRateuint256New exchange rate (18 decimals)
timestampuint256Timestamp of the update

YieldDistributed

Emitted when yield is distributed to stQEURO holders

Used to track yield distributions and their impact

OPTIMIZED: Indexed exchange rate for efficient filtering

event YieldDistributed(uint256 yieldAmount, uint256 indexed newExchangeRate);

Parameters

NameTypeDescription
yieldAmountuint256Amount of yield distributed (18 decimals)
newExchangeRateuint256New exchange rate after distribution (18 decimals)

YieldClaimed

Emitted when a user claims yield

Indexed parameters allow efficient filtering of events

event YieldClaimed(address indexed user, uint256 yieldAmount);

Parameters

NameTypeDescription
useraddressAddress of the user who claimed yield
yieldAmountuint256Amount of yield claimed (18 decimals)

YieldParametersUpdated

Emitted when yield parameters are updated

Used to track parameter changes by governance

OPTIMIZED: Indexed parameter type for efficient filtering

event YieldParametersUpdated(
    string indexed parameterType, uint256 yieldFee, uint256 minYieldThreshold, uint256 maxUpdateFrequency
);

Parameters

NameTypeDescription
parameterTypestring
yieldFeeuint256New yield fee in basis points
minYieldThresholduint256New minimum yield threshold
maxUpdateFrequencyuint256New maximum update frequency

YieldConversionPriceUpdated

Emitted when the cached yield conversion price is updated

event YieldConversionPriceUpdated(uint256 oldPrice, uint256 newPrice, address indexed caller);

ETHRecovered

Emitted when ETH is recovered to the treasury

event ETHRecovered(address indexed to, uint256 indexed amount);

Parameters

NameTypeDescription
toaddressAddress to which ETH was recovered
amountuint256Amount of ETH recovered

Contents

IAaveVault

Git Source

Title: IAaveVault

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the AaveVault (Aave V3 USDC yield vault)

Mirrors the external/public API of src/core/vaults/AaveVault.sol

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the Aave vault

Initializes the AaveVault 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function emergencyMode() external view returns (bool);

Returns

NameTypeDescription
<none>boolbool True if in emergency mode, false otherwise

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external;

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.

harvestYield

Harvests yield and routes it to YieldShift using adapter-defined source semantics.

Realizes accrued yield without withdrawing tracked principal.

Notes:

  • security: Implementations should restrict unauthorized callers.

  • validation: Implementations should validate source state before harvesting.

  • state-changes: Typically realizes yield and routes it to downstream distribution logic.

  • events: Implementations should emit harvest/yield-routing 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 harvestYield() external returns (uint256 harvestedYield);

Returns

NameTypeDescription
harvestedYielduint256Yield harvested 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

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: Emits HedgingRewardsClaimed.

  • 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 SingleHedgerRotationProposed.

  • 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.

applySingleHedgerRotation

Applies a previously proposed single‑hedger rotation.

Finalizes the transition to pendingSingleHedger once any activation delay has elapsed.

Notes:

  • security: Restricted to governance; relies on internal timing/quorum checks.

  • validation: Reverts if there is no pending rotation or delay not met.

  • state-changes: Updates singleHedger and clears pending rotation state.

  • events: Emits SingleHedgerRotationApplied.

  • errors: Reverts with protocol‑specific rotation errors.

  • reentrancy: Not applicable – configuration only.

  • access: Restricted to governance roles.

  • oracle: No oracle dependency.

function applySingleHedgerRotation() external;

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.

pendingSingleHedger

Returns the pending single hedger address, if any.

When non‑zero, this address will become singleHedger once rotation is applied.

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 pendingSingleHedger() external view returns (address pending);

Returns

NameTypeDescription
pendingaddressAddress that will become the single hedger after rotation is applied.

singleHedgerPendingAt

Returns the timestamp at which the pending single hedger can be applied.

After this timestamp, applySingleHedgerRotation may finalize the rotation.

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 singleHedgerPendingAt() external view returns (uint256 pendingAt);

Returns

NameTypeDescription
pendingAtuint256Unix timestamp when rotation becomes executable.

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);

HedgingRewardsClaimed

event HedgingRewardsClaimed(address indexed hedger, bytes32 packedData);

RewardReserveFunded

event RewardReserveFunded(address indexed funder, uint256 amount);

SingleHedgerRotationProposed

event SingleHedgerRotationProposed(
    address indexed currentHedger, address indexed pendingHedger, uint256 activatesAt
);

SingleHedgerRotationApplied

event SingleHedgerRotationApplied(address indexed previousHedger, address indexed newHedger);

Structs

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;
}

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: May update internal state during price check

  • 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
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Timestamp of last successful update
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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function minPricePrecision() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256precision Minimum price precision value

IQTIToken

Git Source

Title: IQTIToken

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the QTI governance token with vote-escrow mechanics

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the QTI token

Sets up initial roles and configuration for the governance 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function initialize(address admin, address _treasury, address timelock) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_treasuryaddressTreasury address
timelockaddressTimelock address

lock

Lock QTI tokens for voting power

Locks QTI tokens for a specified duration to receive 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Parameters

NameTypeDescription
amountuint256Amount of QTI to lock (18 decimals)
lockTimeuint256Duration to lock (seconds)

Returns

NameTypeDescription
veQTIuint256Voting power received (18 decimals)

unlock

Unlock QTI tokens after lock period expires

Unlocks all expired QTI tokens and returns them to 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unlock() external returns (uint256 amount);

Returns

NameTypeDescription
amountuint256Amount of QTI unlocked (18 decimals)

batchLock

Batch lock QTI tokens for voting power

Locks multiple amounts of QTI tokens with different lock durations

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 batchLock(uint256[] calldata amounts, uint256[] calldata lockTimes)
    external
    returns (uint256[] memory veQTIAmounts);

Parameters

NameTypeDescription
amountsuint256[]Array of amounts to lock (18 decimals each)
lockTimesuint256[]Array of corresponding lock durations (seconds each)

Returns

NameTypeDescription
veQTIAmountsuint256[]Array of voting power received per lock (18 decimals each)

batchUnlock

Batch unlock QTI tokens for multiple users (admin/governance)

Unlocks expired QTI 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchUnlock(address[] calldata users) external returns (uint256[] memory amounts);

Parameters

NameTypeDescription
usersaddress[]Array of user addresses to unlock for

Returns

NameTypeDescription
amountsuint256[]Array of amounts unlocked per user (18 decimals each)

getVotingPower

Get voting power for an address

Returns the current voting power for a user based on their locked 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
votingPoweruint256Current voting power (18 decimals)

updateVotingPower

Update voting power for the caller based on current time

Recalculates and updates voting power based on time 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateVotingPower() external returns (uint256 newVotingPower);

Returns

NameTypeDescription
newVotingPoweruint256Updated voting power (18 decimals)

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getLockInfo(address user)
    external
    view
    returns (
        uint256 amount,
        uint256 unlockTime,
        uint256 votingPower,
        uint256 lastClaimTime,
        uint256 initialVotingPower,
        uint256 lockTime
    );

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
amountuint256Locked amount (18 decimals)
unlockTimeuint256Unlock timestamp
votingPoweruint256Current voting power (18 decimals)
lastClaimTimeuint256Last claim time
initialVotingPoweruint256Initial voting power when locked (18 decimals)
lockTimeuint256Original lock duration (seconds)

createProposal

Create a new governance proposal

Creates a new governance proposal with specified 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function createProposal(string calldata description, uint256 votingPeriod, bytes calldata data)
    external
    returns (uint256 proposalId);

Parameters

NameTypeDescription
descriptionstringProposal description
votingPerioduint256Voting period in seconds
databytesExecution data

Returns

NameTypeDescription
proposalIduint256New proposal ID

vote

Vote on a proposal

Casts a vote on a governance 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function vote(uint256 proposalId, bool support) external;

Parameters

NameTypeDescription
proposalIduint256Proposal ID
supportboolTrue for yes, false for no

batchVote

Batch vote on multiple proposals

Casts votes on multiple governance 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchVote(uint256[] calldata proposalIds, bool[] calldata supportVotes) external;

Parameters

NameTypeDescription
proposalIdsuint256[]Array of proposal IDs
supportVotesbool[]Array of vote choices (true/false)

executeProposal

Execute a successful proposal

Executes a proposal that has passed voting 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: Requires fresh oracle price data

function executeProposal(uint256 proposalId) external;

Parameters

NameTypeDescription
proposalIduint256Proposal ID

cancelProposal

Cancel a proposal

Cancels 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function cancelProposal(uint256 proposalId) external;

Parameters

NameTypeDescription
proposalIduint256Proposal ID

getProposal

Get proposal details

Returns comprehensive information about a governance 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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
proposeraddressProposal creator
startTimeuint256Voting start time
endTimeuint256Voting end time
forVotesuint256Votes in favor (18 decimals)
againstVotesuint256Votes against (18 decimals)
executedboolWhether executed
canceledboolWhether canceled
descriptionstringProposal description

getReceipt

Get voting receipt for a user

Returns voting information for a specific user and 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getReceipt(uint256 proposalId, address voter)
    external
    view
    returns (bool hasVoted, bool support, uint256 votes);

Parameters

NameTypeDescription
proposalIduint256Proposal ID
voteraddressVoter address

Returns

NameTypeDescription
hasVotedboolWhether user voted
supportboolVote direction
votesuint256Number of votes cast (18 decimals)

getProposalExecutionInfo

Gets proposal execution information

Returns execution details for a specific proposal

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 proposal execution info

  • oracle: No oracle dependencies

function getProposalExecutionInfo(uint256 proposalId)
    external
    view
    returns (bytes32 executionHash, uint256 executionTime, address executor);

Parameters

NameTypeDescription
proposalIduint256ID of the proposal

Returns

NameTypeDescription
executionHashbytes32Hash of the execution data
executionTimeuint256Time when proposal was executed
executoraddressAddress that executed the proposal

getProposalExecutionHash

Gets proposal execution hash

Returns the execution hash for a specific proposal

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 proposal execution hash

  • oracle: No oracle dependencies

function getProposalExecutionHash(uint256 proposalId) external view returns (bytes32 executionHash);

Parameters

NameTypeDescription
proposalIduint256ID of the proposal

Returns

NameTypeDescription
executionHashbytes32Hash of the execution data

updateGovernanceParameters

Update governance parameters

Updates key governance parameters for the protocol

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 updateGovernanceParameters(uint256 _proposalThreshold, uint256 _minVotingPeriod, uint256 _quorumVotes)
    external;

Parameters

NameTypeDescription
_proposalThresholduint256New proposal threshold (18 decimals)
_minVotingPerioduint256New minimum voting period (seconds)
_quorumVotesuint256New quorum requirement (18 decimals)

updateTreasury

Update treasury address

Updates the treasury address for protocol fees and 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateTreasury(address _treasury) external;

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

updateDecentralizationLevel

Update decentralization level

Updates the decentralization level based on current protocol 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateDecentralizationLevel() external;

pause

Pause the contract

Pauses all contract 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function pause() external;

unpause

Unpause the contract

Resumes all contract 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unpause() external;

getGovernanceInfo

Get governance information

Returns comprehensive governance 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getGovernanceInfo()
    external
    view
    returns (
        uint256 _totalLocked,
        uint256 _totalVotingPower,
        uint256 _proposalThreshold,
        uint256 _quorumVotes,
        uint256 _currentDecentralizationLevel
    );

Returns

NameTypeDescription
_totalLockeduint256Total locked QTI (18 decimals)
_totalVotingPoweruint256Total voting power (18 decimals)
_proposalThresholduint256Proposal threshold (18 decimals)
_quorumVotesuint256Quorum requirement (18 decimals)
_currentDecentralizationLeveluint256Current decentralization level

name

Get the token name

Returns the name of the QTI 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function name() external view returns (string memory);

Returns

NameTypeDescription
<none>stringname The token name string

symbol

Get the token symbol

Returns the symbol of the QTI 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function symbol() external view returns (string memory);

Returns

NameTypeDescription
<none>stringsymbol The token symbol string

decimals

Get the token decimals

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function decimals() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8decimals The number of decimals (always 18)

totalSupply

Get the total token supply

Returns the total supply of QTI 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function totalSupply() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256totalSupply The total supply (18 decimals)

balanceOf

Get the 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Parameters

NameTypeDescription
accountaddressAddress to query

Returns

NameTypeDescription
<none>uint256balance The token balance (18 decimals)

transfer

Transfer QTI tokens to another address

Standard ERC20 transfer 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 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 account has a specific role

Returns true if the account has the specified 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>boolbool True if account has the role, false otherwise

getRoleAdmin

Get the admin role for a specific role

Returns the admin role that can grant/revoke the specified 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>bytes32bytes32 The admin role

grantRole

Grant a role to an account

Grants the specified role to the account

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

Revoke a role from an account

Revokes the specified role from the account

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

Renounce a role

Allows an account to renounce 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
callerConfirmationaddressThe caller's address for confirmation

paused

Check 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>boolbool True if paused, false if not paused

upgradeTo

Upgrade the contract implementation

Upgrades the contract to a new implementation

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

upgradeToAndCall

Upgrade the contract implementation with initialization

Upgrades the contract to a new implementation and calls initialization function

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
databytesInitialization data to call on new implementation

GOVERNANCE_ROLE

Returns the governance role identifier

Role required for governance 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 governance role

  • oracle: No oracle dependencies

function GOVERNANCE_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The governance role identifier

EMERGENCY_ROLE

Returns the emergency role identifier

Role required for 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 emergency role

  • oracle: No oracle dependencies

function EMERGENCY_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The emergency role identifier

UPGRADER_ROLE

Returns the upgrader role identifier

Role required for contract upgrades

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 upgrader role

  • oracle: No oracle dependencies

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32bytes32 The upgrader role identifier

MAX_LOCK_TIME

Returns the maximum lock time

Maximum duration tokens can be locked for (seconds)

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 maximum lock time

  • oracle: No oracle dependencies

function MAX_LOCK_TIME() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Maximum lock time in seconds

MIN_LOCK_TIME

Returns the minimum lock time

Minimum duration tokens must be locked for (seconds)

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 lock time

  • oracle: No oracle dependencies

function MIN_LOCK_TIME() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Minimum lock time in seconds

WEEK

Returns the week duration

Duration of one week in seconds

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 week duration

  • oracle: No oracle dependencies

function WEEK() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Week duration in seconds

MAX_VE_QTI_MULTIPLIER

Returns the maximum veQTI multiplier

Maximum voting power multiplier for locked tokens

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 maximum veQTI multiplier

  • oracle: No oracle dependencies

function MAX_VE_QTI_MULTIPLIER() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Maximum veQTI multiplier

MAX_TIME_ELAPSED

Returns the maximum time elapsed

Maximum time that can elapse for calculations

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 maximum time elapsed

  • oracle: No oracle dependencies

function MAX_TIME_ELAPSED() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Maximum time elapsed in seconds

TOTAL_SUPPLY_CAP

Returns the total supply cap

Maximum total supply of QTI tokens (18 decimals)

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 supply cap

  • oracle: No oracle dependencies

function TOTAL_SUPPLY_CAP() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total supply cap in QTI tokens

locks

Returns lock information for an address

Returns comprehensive lock information for a user

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 lock information

  • oracle: No oracle dependencies

function locks(address user)
    external
    view
    returns (
        uint256 amount,
        uint256 unlockTime,
        uint256 votingPower,
        uint256 lastClaimTime,
        uint256 initialVotingPower,
        uint256 lockTime
    );

Parameters

NameTypeDescription
useraddressAddress of the user to query

Returns

NameTypeDescription
amountuint256Locked amount (18 decimals)
unlockTimeuint256Unlock timestamp
votingPoweruint256Current voting power (18 decimals)
lastClaimTimeuint256Last claim time
initialVotingPoweruint256Initial voting power when locked (18 decimals)
lockTimeuint256Original lock duration (seconds)

totalLocked

Returns total locked QTI tokens

Total amount of QTI tokens locked across all users (18 decimals)

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 locked

  • oracle: No oracle dependencies

function totalLocked() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total locked QTI tokens

totalVotingPower

Returns total voting power

Total voting power across all locked tokens (18 decimals)

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 voting power

  • oracle: No oracle dependencies

function totalVotingPower() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Total voting power

proposals

Returns proposal information by ID

Returns comprehensive proposal information

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 proposal information

  • oracle: No oracle dependencies

function proposals(uint256 proposalId)
    external
    view
    returns (
        address proposer,
        uint256 startTime,
        uint256 endTime,
        uint256 forVotes,
        uint256 againstVotes,
        bool executed,
        bool canceled,
        string memory description
    );

Parameters

NameTypeDescription
proposalIduint256ID of the proposal to query

Returns

NameTypeDescription
proposeraddressProposal creator address
startTimeuint256Voting start timestamp
endTimeuint256Voting end timestamp
forVotesuint256Votes in favor (18 decimals)
againstVotesuint256Votes against (18 decimals)
executedboolWhether proposal was executed
canceledboolWhether proposal was canceled
descriptionstringProposal description

nextProposalId

Returns the next proposal ID

Counter for generating unique proposal IDs

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 next proposal ID

  • oracle: No oracle dependencies

function nextProposalId() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Next proposal ID

proposalThreshold

Returns the proposal threshold

Minimum voting power required to create proposals (18 decimals)

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 proposal threshold

  • oracle: No oracle dependencies

function proposalThreshold() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Proposal threshold in QTI tokens

minVotingPeriod

Returns the minimum voting period

Minimum duration for proposal voting (seconds)

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 voting period

  • oracle: No oracle dependencies

function minVotingPeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Minimum voting period in seconds

maxVotingPeriod

Returns the maximum voting period

Maximum duration for proposal voting (seconds)

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 maximum voting period

  • oracle: No oracle dependencies

function maxVotingPeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Maximum voting period in seconds

quorumVotes

Returns the quorum votes requirement

Minimum votes required for proposal execution (18 decimals)

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 quorum votes

  • oracle: No oracle dependencies

function quorumVotes() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Quorum votes requirement in QTI tokens

treasury

Returns the treasury address

Address where protocol fees and rewards are sent

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 treasury address

  • oracle: No oracle dependencies

function treasury() external view returns (address);

Returns

NameTypeDescription
<none>addressaddress Treasury address

decentralizationStartTime

Returns the decentralization start time

Timestamp when decentralization process began

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 decentralization start time

  • oracle: No oracle dependencies

function decentralizationStartTime() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Decentralization start timestamp

decentralizationDuration

Returns the decentralization duration

Duration of the decentralization process (seconds)

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 decentralization duration

  • oracle: No oracle dependencies

function decentralizationDuration() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Decentralization duration in seconds

currentDecentralizationLevel

Returns the current decentralization level

Current level of protocol decentralization (0-100)

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 decentralization level

  • oracle: No oracle dependencies

function currentDecentralizationLevel() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 Current decentralization level

recoverToken

Recovers tokens accidentally sent to the contract

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: Emits TokenRecovered event

  • 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;

Parameters

NameTypeDescription
tokenaddressAddress of the token to recover
amountuint256Amount of tokens to recover

recoverETH

Recovers ETH accidentally sent to the contract

Emergency function to recover ETH that was accidentally sent to the contract

Notes:

  • security: Validates admin role and emits recovery event

  • validation: No input validation required - transfers all ETH

  • state-changes: Transfers all contract ETH balance to treasury

  • events: Emits ETHRecovered with amount and treasury address

  • errors: No errors thrown - safe ETH transfer

  • reentrancy: Not protected - no external calls

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function recoverETH() external;

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

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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.

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

getVaultMetrics

Retrieves the vault's global metrics

Provides comprehensive vault statistics for monitoring and analysis

Notes:

  • security: Read-only helper

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Not applicable

  • access: Public

  • oracle: Uses cached oracle price for debt-value conversion

function getVaultMetrics()
    external
    view
    returns (
        uint256 totalUsdcHeld_,
        uint256 totalMinted_,
        uint256 totalDebtValue,
        uint256 totalUsdcInExternalVaults_,
        uint256 totalUsdcAvailable_
    );

Returns

NameTypeDescription
totalUsdcHeld_uint256Total USDC held directly in the vault
totalMinted_uint256Total QEURO minted
totalDebtValueuint256Total debt value in USD
totalUsdcInExternalVaults_uint256Total USDC principal deployed across external vault adapters
totalUsdcAvailable_uint256Total USDC available (vault + external adapters)

calculateMintAmount

Computes QEURO mint amount for a USDC swap

Uses cached oracle price to calculate QEURO equivalent without executing swap

Notes:

  • security: Read-only helper

  • validation: Returns zeroes when price cache is uninitialized

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Not applicable

  • access: Public

  • oracle: Uses cached oracle price only

function calculateMintAmount(uint256 usdcAmount) external view returns (uint256 qeuroAmount, uint256 fee);

Parameters

NameTypeDescription
usdcAmountuint256USDC to swap

Returns

NameTypeDescription
qeuroAmountuint256Expected QEURO to mint (after fees)
feeuint256Protocol fee

calculateRedeemAmount

Computes USDC redemption amount for a QEURO swap

Uses cached oracle price to calculate USDC equivalent without executing swap

Notes:

  • security: Read-only helper

  • validation: Returns zeroes when price cache is uninitialized

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: Not applicable

  • access: Public

  • oracle: Uses cached oracle price only

function calculateRedeemAmount(uint256 qeuroAmount) external view returns (uint256 usdcAmount, uint256 fee);

Parameters

NameTypeDescription
qeuroAmountuint256QEURO to swap

Returns

NameTypeDescription
usdcAmountuint256USDC returned after fees
feeuint256Protocol fee

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to GOVERNANCE_ROLE

  • oracle: No oracle dependencies

function updateUserPool(address _userPool) external;

Parameters

NameTypeDescription
_userPooladdressNew UserPool address

getPriceProtectionStatus

Gets the price protection status and parameters

Returns price protection configuration for monitoring

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 price protection status

  • oracle: No oracle dependencies

function getPriceProtectionStatus()
    external
    view
    returns (uint256 lastValidPrice, uint256 lastUpdateBlock, uint256 maxDeviation, uint256 minBlocks);

Returns

NameTypeDescription
lastValidPriceuint256Last valid EUR/USD price
lastUpdateBlockuint256Block number of last price update
maxDeviationuint256Maximum allowed price deviation
minBlocksuint256Minimum blocks between price updates

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: Protected by 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: Protected by 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 current collateralization ratio

Returns true if collateralization ratio < criticalCollateralizationRatio

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 liquidation status

  • oracle: No oracle dependencies

function shouldTriggerLiquidation() external view returns (bool);

Returns

NameTypeDescription
<none>boolshouldLiquidate Whether liquidation should be triggered

getLiquidationStatus

Returns liquidation status and key metrics for pro-rata redemption

Protocol enters liquidation mode when CR <= 101%

Notes:

  • security: View function - no state changes

  • validation: No input validation required

  • state-changes: None - view function

  • events: None

  • errors: None

  • reentrancy: Not applicable - view function

  • access: Public - anyone can check liquidation status

  • oracle: Requires oracle price for collateral calculation

function getLiquidationStatus()
    external
    view
    returns (
        bool isInLiquidation,
        uint256 collateralizationRatioBps,
        uint256 totalCollateralUsdc,
        uint256 totalQeuroSupply
    );

Returns

NameTypeDescription
isInLiquidationboolTrue if protocol is in liquidation mode
collateralizationRatioBpsuint256Current CR in basis points
totalCollateralUsdcuint256Total protocol collateral in USDC (6 decimals)
totalQeuroSupplyuint256Total QEURO supply (18 decimals)

calculateLiquidationPayout

Calculates pro-rata payout for liquidation mode redemption

Formula: payout = (qeuroAmount / totalSupply) * totalCollateral

Notes:

  • security: View function - no state changes

  • validation: Validates qeuroAmount > 0

  • state-changes: None - view function

  • events: None

  • errors: Throws InvalidAmount if qeuroAmount is 0

  • reentrancy: Not applicable - view function

  • access: Public - anyone can calculate payout

  • oracle: Requires oracle price for fair value calculation

function calculateLiquidationPayout(uint256 qeuroAmount)
    external
    view
    returns (uint256 usdcPayout, bool isPremium, uint256 premiumOrDiscountBps);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to redeem (18 decimals)

Returns

NameTypeDescription
usdcPayoutuint256Amount of USDC the user would receive (6 decimals)
isPremiumboolTrue if payout > fair value (CR > 100%)
premiumOrDiscountBpsuint256Premium or discount in basis points

redeemQEUROLiquidation

Redeems QEURO for USDC using pro-rata distribution in liquidation mode

Only callable when protocol is in liquidation mode (CR <= 101%)

Notes:

  • security: Protected by nonReentrant, requires liquidation mode

  • validation: Validates qeuroAmount > 0, minUsdcOut slippage, liquidation mode

  • state-changes: Burns QEURO, transfers USDC pro-rata

  • events: Emits LiquidationRedeemed

  • errors: Reverts if not in liquidation mode or slippage exceeded

  • reentrancy: Protected by nonReentrant modifier

  • access: Public - anyone with QEURO can redeem

  • oracle: Requires oracle price for collateral calculation

function redeemQEUROLiquidation(uint256 qeuroAmount, uint256 minUsdcOut) external;

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to redeem (18 decimals)
minUsdcOutuint256Minimum USDC expected (slippage protection)

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: Requires fresh oracle price data (via HedgerPool)

function getProtocolCollateralizationRatio() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256ratio Current collateralization ratio in 1e18-scaled percentage format

getProtocolCollateralizationRatioView

View-only collateralization ratio using cached price.

Returns the same units as getProtocolCollateralizationRatio() but relies solely on the cached EUR/USD price to remain view-safe (no external oracle calls).

Notes:

  • security: View helper; does not mutate state or touch external oracles.

  • validation: Returns a stale or sentinel value if the cache is uninitialized.

  • state-changes: None – pure view over cached pricing and vault balances.

  • events: None.

  • errors: None – callers must handle edge cases (e.g. 0 collateral).

  • reentrancy: Not applicable – view function only.

  • access: Public – intended for dashboards and off‑chain monitoring.

  • oracle: Uses only the last cached price maintained on-chain.

function getProtocolCollateralizationRatioView() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256ratio Cached collateralization ratio in 1e18‑scaled percentage format.

canMintView

View-only mintability check using cached price and current hedger status.

Equivalent to canMint() but guaranteed not to perform fresh oracle reads, making it safe for off‑chain calls that must not revert due to oracle issues.

Notes:

  • security: Read‑only helper; never mutates state or external dependencies.

  • validation: Returns false on uninitialized cache or missing hedger configuration.

  • state-changes: None – pure read of cached price and protocol state.

  • events: None.

  • errors: None – callers interpret the boolean.

  • reentrancy: Not applicable – view function only.

  • access: Public – anyone can pre‑check mint conditions.

  • oracle: Uses cached price only; no live oracle reads.

function canMintView() external view returns (bool);

Returns

NameTypeDescription
<none>boolcanMintCached True if, based on cached price and current hedger state, minting would be allowed.

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).

harvestVaultYield

Harvests yield from a configured external vault id.

Governance-triggered adapter harvest operation.

Notes:

  • security: Restricted to governance in implementation.

  • validation: Reverts when vault id is invalid/inactive or adapter is unset.

  • state-changes: May update adapter and downstream yield accounting.

  • events: Emits vault-yield harvested event in implementation.

  • errors: Reverts on configuration or adapter failures.

  • reentrancy: Implementation is expected to guard with nonReentrant.

  • access: Governance-only in implementation.

  • oracle: No direct oracle dependency.

function harvestVaultYield(uint256 vaultId) external returns (uint256 harvestedYield);

Parameters

NameTypeDescription
vaultIduint256Vault id to harvest.

Returns

NameTypeDescription
harvestedYielduint256Yield harvested in USDC units.

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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; // HIGH-1: proxy that initiated this upgrade
    uint256 proposedAt;
    uint256 executableAt;
    uint256 expiryAt; // LOW-6: 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function initialize(
    address admin,
    address _qeuro,
    address _usdc,
    address _vault,
    address _yieldShift,
    address _timelock,
    address _treasury
) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_qeuroaddressQEURO token address
_usdcaddressUSDC token address
_vaultaddressVault 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 usdcAmount, uint256 minQeuroOut) external returns (uint256 qeuroMinted);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit
minQeuroOutuint256Minimum QEURO expected (slippage protection)

Returns

NameTypeDescription
qeuroMinteduint256Amount 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 qeuroAmount, uint256 minUsdcOut) external returns (uint256 usdcReceived);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to burn
minUsdcOutuint256Minimum USDC expected

Returns

NameTypeDescription
usdcReceiveduint256USDC 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: Requires fresh oracle price data

function stake(uint256 qeuroAmount) external;

Parameters

NameTypeDescription
qeuroAmountuint256Amount 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: Requires fresh oracle price data

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: Requires fresh oracle price data

function unstake() external;

claimStakingRewards

Claim accumulated staking rewards

Claims all accumulated staking rewards for 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function claimStakingRewards() external returns (uint256 rewardAmount);

Returns

NameTypeDescription
rewardAmountuint256Amount of rewards claimed

getUserDeposits

Get a user's total deposits (USDC equivalent)

Returns the total USDC equivalent value of user's 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getUserDeposits(address user) external view returns (uint256);

Parameters

NameTypeDescription
useraddressAddress to query

Returns

NameTypeDescription
<none>uint256Total deposits in USDC equivalent

getUserStakes

Get a user's total staked QEURO

Returns the total amount of QEURO staked by the 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getUserStakes(address user) external view returns (uint256);

Parameters

NameTypeDescription
useraddressAddress to query

Returns

NameTypeDescription
<none>uint256Total staked QEURO amount

getUserPendingRewards

Get a user's pending staking rewards

Returns the amount of staking rewards available to claim

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getUserPendingRewards(address user) external view returns (uint256);

Parameters

NameTypeDescription
useraddressAddress to query

Returns

NameTypeDescription
<none>uint256Pending staking rewards amount

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Total USDC-equivalent deposits in the pool

Returns the total value of all deposits 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getTotalDeposits() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total deposits 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

getStakingAPY

Current staking APY (bps)

Returns the current annual percentage yield for staking

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getStakingAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current staking APY in basis points

getDepositAPY

Current base deposit APY (bps)

Returns the current annual percentage yield 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getDepositAPY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Current deposit APY in basis points

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateStakingParameters(
    uint256 _stakingAPY,
    uint256 _depositAPY,
    uint256 _minStakeAmount,
    uint256 _unstakingCooldown
) external;

Parameters

NameTypeDescription
_stakingAPYuint256New staking APY (bps)
_depositAPYuint256New base deposit 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function emergencyUnstake(address user) external;

Parameters

NameTypeDescription
useraddressUser address

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unpause() external;

getPoolConfig

Pool configuration snapshot

Returns current pool configuration parameters

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 getPoolConfig()
    external
    view
    returns (
        uint256 _stakingAPY,
        uint256 _depositAPY,
        uint256 _minStakeAmount,
        uint256 _unstakingCooldown,
        uint256 _performanceFee
    );

Returns

NameTypeDescription
_stakingAPYuint256Staking APY (bps)
_depositAPYuint256Deposit APY (bps)
_minStakeAmountuint256Minimum stake amount
_unstakingCooldownuint256Unstaking cooldown seconds
_performanceFeeuint256Performance fee on staking rewards (bps)

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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 input parameters and enforces security checks

  • validation: Validates input parameters and 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 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrader role bytes32 identifier

BLOCKS_PER_DAY

Returns the number of blocks per day

Used 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function BLOCKS_PER_DAY() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of blocks per day

MAX_REWARD_PERIOD

Returns the maximum reward period

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function MAX_REWARD_PERIOD() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Maximum reward period in seconds

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function performanceFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Performance fee in basis points

totalDeposits

Returns the total deposits

Total USDC equivalent value of all 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function totalDeposits() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total deposits in USDC equivalent

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external;

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 _aaveVault,
    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).
_aaveVaultaddressAaveVault 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")).

claimUserYield

Claims accumulated user yield for a specific address.

Enforces holding period via lastDepositTime before releasing USDC yield.

Notes:

  • security: Callable by user or UserPool; checks holding period and pool balances.

  • validation: Reverts if holding period not met or pool has insufficient yield.

  • state-changes: Updates userPendingYield, userLastClaim, userYieldPool, totalYieldDistributed.

  • events: Emits UserYieldClaimed.

  • errors: Reverts with holding‑period or insufficient‑yield errors.

  • reentrancy: Protected by nonReentrant modifier in implementation.

  • access: Restricted to user or UserPool contract.

  • oracle: No direct oracle dependency.

function claimUserYield(address user) external returns (uint256 yieldAmount);

Parameters

NameTypeDescription
useraddressAddress whose yield is being claimed.

Returns

NameTypeDescription
yieldAmountuint256Amount of USDC yield transferred to user.

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.

Reads per‑user pending yield that can be claimed via claimUserYield.

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 aaveVault;
    address stQEUROFactory;
    address treasury;
}

IstQEURO

Git Source

Title: IstQEURO

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Interface for the stQEURO yield-bearing wrapper token (yield accrual mechanism)

Note: security-contact: team@quantillon.money

Functions

initialize

Initializes the stQEURO token

Sets up the stQEURO token with initial configuration and assigns roles to admin

Notes:

  • security: Validates all addresses are not zero and initializes roles

  • validation: Validates admin is not address(0), all contract addresses are valid

  • state-changes: Initializes roles, sets contract addresses, enables staking

  • events: Emits role assignment and initialization events

  • errors: Throws InvalidAddress if any address is zero

  • reentrancy: Protected by onlyInitializing modifier

  • access: Internal function - only callable during initialization

  • oracle: No oracle dependencies

function initialize(
    address admin,
    address _qeuro,
    address _yieldShift,
    address _usdc,
    address _treasury,
    address timelock
) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_qeuroaddressQEURO token address
_yieldShiftaddressYieldShift contract address
_usdcaddressUSDC token address
_treasuryaddressTreasury address
timelockaddressTimelock contract address

initialize

Initializes the stQEURO token with dynamic metadata for a vault.

Configures dependencies and vault-specific token metadata for proxy deployment.

Notes:

  • security: Validates critical dependency addresses and initializes role-gated configuration.

  • validation: Implementations should reject zero/invalid addresses and malformed metadata inputs.

  • state-changes: Initializes metadata, core dependencies, and role assignments.

  • events: Emits initialization and role-grant related events in implementation.

  • errors: Reverts on invalid initialization parameters.

  • reentrancy: Protected by initializer semantics in implementation.

  • access: Public initializer for proxy deployment flow.

  • oracle: No direct oracle dependency during initialization.

function initialize(
    address admin,
    address _qeuro,
    address _yieldShift,
    address _usdc,
    address _treasury,
    address timelock,
    string calldata _tokenName,
    string calldata _tokenSymbol,
    string calldata _vaultName
) external;

Parameters

NameTypeDescription
adminaddressAdmin address
_qeuroaddressQEURO token address
_yieldShiftaddressYieldShift contract address
_usdcaddressUSDC token address
_treasuryaddressTreasury address
timelockaddressTimelock contract address
_tokenNamestringERC20 token name for this vault token instance
_tokenSymbolstringERC20 token symbol for this vault token instance
_vaultNamestringHuman-readable vault name

stake

Stake QEURO to receive stQEURO

Converts QEURO to stQEURO at current exchange rate with yield accrual

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 stake(uint256 qeuroAmount) external returns (uint256 stQEUROAmount);

Parameters

NameTypeDescription
qeuroAmountuint256Amount of QEURO to stake

Returns

NameTypeDescription
stQEUROAmountuint256Amount of stQEURO received

unstake

Unstake QEURO by burning stQEURO

Converts stQEURO back to QEURO at current exchange rate

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 unstake(uint256 stQEUROAmount) external returns (uint256 qeuroAmount);

Parameters

NameTypeDescription
stQEUROAmountuint256Amount of stQEURO to burn

Returns

NameTypeDescription
qeuroAmountuint256Amount of QEURO received

batchStake

Batch stake QEURO amounts

Efficiently stakes multiple QEURO amounts 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchStake(uint256[] calldata qeuroAmounts) external returns (uint256[] memory stQEUROAmounts);

Parameters

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO amounts

Returns

NameTypeDescription
stQEUROAmountsuint256[]Array of stQEURO minted

batchUnstake

Batch unstake stQEURO amounts

Efficiently unstakes multiple stQEURO amounts 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchUnstake(uint256[] calldata stQEUROAmounts) external returns (uint256[] memory qeuroAmounts);

Parameters

NameTypeDescription
stQEUROAmountsuint256[]Array of stQEURO amounts

Returns

NameTypeDescription
qeuroAmountsuint256[]Array of QEURO returned

batchTransfer

Batch transfer stQEURO to multiple recipients

Efficiently transfers stQEURO 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 reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) external returns (bool);

Parameters

NameTypeDescription
recipientsaddress[]Array of recipient addresses
amountsuint256[]Array of amounts to transfer

Returns

NameTypeDescription
<none>boolsuccess True if all transfers succeeded

distributeYield

Distribute yield to stQEURO holders (increases exchange rate)

Distributes yield by increasing the exchange rate for all stQEURO holders

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 distributeYield(uint256 yieldAmount) external;

Parameters

NameTypeDescription
yieldAmountuint256Amount of yield in USDC

claimYield

Claim accumulated yield for a user (in USDC)

Claims the user's accumulated yield and transfers it to their 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function claimYield() external returns (uint256 yieldAmount);

Returns

NameTypeDescription
yieldAmountuint256Amount of yield claimed

getPendingYield

Get pending yield for a user (in USDC)

Returns the amount of yield available for a specific user to claim

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getPendingYield(address user) external view returns (uint256 yieldAmount);

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
yieldAmountuint256Pending yield amount

getExchangeRate

Get current exchange rate between QEURO and stQEURO

Returns the current exchange rate used for staking/unstaking 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getExchangeRate() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256exchangeRate Current exchange rate (18 decimals)

getTVL

Get total value locked in stQEURO

Returns the total value locked in the stQEURO 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getTVL() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256tvl Total value locked (18 decimals)

getQEUROEquivalent

Get user's QEURO equivalent balance

Returns the QEURO equivalent value of a user's stQEURO balance

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and 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 getQEUROEquivalent(address user) external view returns (uint256 qeuroEquivalent);

Parameters

NameTypeDescription
useraddressUser address

Returns

NameTypeDescription
qeuroEquivalentuint256QEURO equivalent of stQEURO balance

getStakingStats

Get staking statistics

Returns comprehensive staking 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function getStakingStats()
    external
    view
    returns (
        uint256 totalStQEUROSupply,
        uint256 totalQEUROUnderlying,
        uint256 currentExchangeRate,
        uint256 _totalYieldEarned,
        uint256 apy
    );

Returns

NameTypeDescription
totalStQEUROSupplyuint256Total stQEURO supply
totalQEUROUnderlyinguint256Total QEURO underlying
currentExchangeRateuint256Current exchange rate
_totalYieldEarneduint256Total yield earned
apyuint256Annual percentage yield

updateYieldParameters

Update yield parameters

Updates yield-related parameters 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function updateYieldParameters(uint256 _yieldFee, uint256 _minYieldThreshold, uint256 _maxUpdateFrequency) external;

Parameters

NameTypeDescription
_yieldFeeuint256New yield fee percentage
_minYieldThresholduint256New minimum yield threshold
_maxUpdateFrequencyuint256New maximum update frequency

updateTreasury

Update treasury address

Updates the treasury address 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 updateTreasury(address _treasury) external;

Parameters

NameTypeDescription
_treasuryaddressNew treasury address

pause

Pause the contract

Pauses all stQEURO 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function pause() external;

unpause

Unpause the contract

Resumes all stQEURO 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function unpause() external;

emergencyWithdraw

Emergency withdrawal of QEURO

Allows emergency withdrawal of QEURO for a specific 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function emergencyWithdraw(address user) external;

Parameters

NameTypeDescription
useraddressUser address to withdraw for

recoverToken

Recover accidentally sent tokens

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverToken(address token, uint256 amount) external;

Parameters

NameTypeDescription
tokenaddressToken address to recover
amountuint256Amount to transfer

recoverETH

Recover accidentally sent ETH

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function recoverETH() external;

name

Returns the name of the token

Returns the token name for display 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 token name

  • oracle: No oracle dependencies

function name() external view returns (string memory);

Returns

NameTypeDescription
<none>stringThe token name

symbol

Returns the symbol of the token

Returns the token symbol for display 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 token symbol

  • oracle: No oracle dependencies

function symbol() external view returns (string memory);

Returns

NameTypeDescription
<none>stringThe token symbol

decimals

Returns the decimals of the token

Returns the number of decimals used for token amounts

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 decimals

  • oracle: No oracle dependencies

function decimals() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8The number of decimals

totalSupply

Returns the total supply of the token

Returns the total amount of tokens in existence

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 supply

  • oracle: No oracle dependencies

function totalSupply() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total supply

balanceOf

Returns the balance of an account

Returns the token balance of the specified account

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 account balance

  • oracle: No oracle dependencies

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

Parameters

NameTypeDescription
accountaddressThe account to check

Returns

NameTypeDescription
<none>uint256The balance of the account

transfer

Transfers tokens to a recipient

Transfers the specified amount of tokens to the recipient

Notes:

  • security: Validates recipient is not address(0) and caller has sufficient balance

  • validation: Validates to != address(0) and amount <= balanceOf(msg.sender)

  • state-changes: Updates balances of sender and recipient

  • events: Emits Transfer event

  • errors: Throws InsufficientBalance if amount > balance

  • reentrancy: Not protected - no external calls

  • access: Public - any token holder can transfer

  • oracle: No oracle dependencies

function transfer(address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
toaddressThe recipient address
amountuint256The amount to transfer

Returns

NameTypeDescription
<none>boolTrue if the transfer succeeded

allowance

Returns the allowance for a spender

Returns the amount of tokens that the spender is allowed to spend

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 allowance

  • oracle: No oracle dependencies

function allowance(address owner, address spender) external view returns (uint256);

Parameters

NameTypeDescription
owneraddressThe owner address
spenderaddressThe spender address

Returns

NameTypeDescription
<none>uint256The allowance amount

approve

Approves a spender to spend tokens

Sets the allowance for the spender to spend tokens on behalf of the caller

Notes:

  • security: Validates spender is not address(0)

  • validation: Validates spender != address(0)

  • state-changes: Updates allowance mapping

  • events: Emits Approval event

  • errors: No errors thrown - safe function

  • reentrancy: Not protected - no external calls

  • access: Public - any token holder can approve

  • oracle: No oracle dependencies

function approve(address spender, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
spenderaddressThe spender address
amountuint256The amount to approve

Returns

NameTypeDescription
<none>boolTrue if the approval succeeded

transferFrom

Transfers tokens from one account to another

Transfers tokens from the from account to the to account

Notes:

  • security: Validates recipient is not address(0) and sufficient allowance

  • validation: Validates to != address(0) and amount <= allowance(from, msg.sender)

  • state-changes: Updates balances and allowance

  • events: Emits Transfer event

  • errors: Throws InsufficientAllowance if amount > allowance

  • reentrancy: Not protected - no external calls

  • access: Public - any approved spender can transfer

  • oracle: No oracle dependencies

function transferFrom(address from, address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
fromaddressThe sender address
toaddressThe recipient address
amountuint256The amount to transfer

Returns

NameTypeDescription
<none>boolTrue if the transfer succeeded

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

Returns the admin role for a 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 check

Returns

NameTypeDescription
<none>bytes32The admin role

grantRole

Grants a role to an account

Grants the specified role to the account

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

Revokes the specified role from the account

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

Renounces the specified role from the caller

Notes:

  • security: Validates caller is renouncing their own role

  • validation: Validates callerConfirmation == msg.sender

  • state-changes: Removes role from caller

  • events: Emits RoleRenounced event

  • errors: Throws AccessControlInvalidCaller 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
callerConfirmationaddressThe caller confirmation

paused

Returns the paused state

Returns true if the contract is 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

upgradeTo

Upgrades the implementation

Upgrades the contract to a new implementation

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
newImplementationaddressThe new implementation address

upgradeToAndCall

Upgrades the implementation and calls a function

Upgrades the contract and calls a function on the new implementation

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
newImplementationaddressThe new implementation address
databytesThe function call data

GOVERNANCE_ROLE

Returns the governance role

Returns the role identifier for 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

YIELD_MANAGER_ROLE

Returns the yield manager role

Returns the role identifier for yield management 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 YIELD_MANAGER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The yield manager role

EMERGENCY_ROLE

Returns the emergency role

Returns the role identifier for emergency 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 EMERGENCY_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The emergency role

UPGRADER_ROLE

Returns the upgrader role

Returns the role identifier for upgrade 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 UPGRADER_ROLE() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32The upgrader role

qeuro

Returns the QEURO token address

Returns the address of the underlying QEURO token

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>addressThe QEURO token address

yieldShift

Returns the YieldShift contract address

Returns the address of the YieldShift contract

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 contract address

  • oracle: No oracle dependencies

function yieldShift() external view returns (address);

Returns

NameTypeDescription
<none>addressThe YieldShift contract address

usdc

Returns the USDC token address

Returns the address of the USDC token

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>addressThe USDC token address

treasury

Returns the treasury address

Returns the address of the treasury contract

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 treasury address

  • oracle: No oracle dependencies

function treasury() external view returns (address);

Returns

NameTypeDescription
<none>addressThe treasury address

exchangeRate

Returns the current exchange rate

Returns the current exchange rate between QEURO and stQEURO

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 exchange rate

  • oracle: No oracle dependencies

function exchangeRate() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The current exchange rate

lastUpdateTime

Returns the last update time

Returns the timestamp of the last exchange rate update

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 last update time

  • oracle: No oracle dependencies

function lastUpdateTime() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The last update time

totalUnderlying

Returns the total underlying QEURO

Returns the total amount of QEURO underlying all stQEURO

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 underlying

  • oracle: No oracle dependencies

function totalUnderlying() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total underlying QEURO

totalYieldEarned

Returns the total yield earned

Returns the total amount of yield earned by all stQEURO holders

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 yield earned

  • oracle: No oracle dependencies

function totalYieldEarned() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total yield earned

yieldFee

Returns the yield fee percentage

Returns the percentage of yield that goes to the treasury

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 yield fee

  • oracle: No oracle dependencies

function yieldFee() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The yield fee percentage

minYieldThreshold

Returns the minimum yield threshold

Returns the minimum yield amount required for distribution

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 yield threshold

  • oracle: No oracle dependencies

function minYieldThreshold() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The minimum yield threshold

maxUpdateFrequency

Returns the maximum update frequency

Returns the maximum frequency for exchange rate updates

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 maximum update frequency

  • oracle: No oracle dependencies

function maxUpdateFrequency() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The maximum update frequency

getVirtualProtectionStatus

Gets the virtual protection status and parameters

Returns virtual protection configuration for monitoring

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 virtual protection status

  • oracle: No oracle dependencies

function getVirtualProtectionStatus()
    external
    view
    returns (bool isEnabled, uint256 maxDeviation, uint256 lastUpdateTimestamp, uint256 virtualPrice);

Returns

NameTypeDescription
isEnabledboolWhether virtual protection is enabled
maxDeviationuint256Maximum allowed deviation from real price
lastUpdateTimestampuint256Last time the virtual price was updated
virtualPriceuint256Current virtual price

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

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

onlyVaultManager

Ensures the caller has vault manager role

Reverts with NotVaultManager if caller lacks VAULT_MANAGER_ROLE

Notes:

  • security: Validates caller has VAULT_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 NotVaultManager if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyVaultManager(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

onlyLiquidatorRole

Ensures the caller has liquidator role

Reverts with NotLiquidatorRole if caller lacks LIQUIDATOR_ROLE

Notes:

  • security: Validates caller has LIQUIDATOR_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 NotLiquidatorRole if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: Internal function - no access restrictions

  • oracle: No oracle dependencies

function onlyLiquidatorRole(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

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

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();

ConfigInvalid

error ConfigInvalid();

NotAdmin

error NotAdmin();

InvalidAdmin

error InvalidAdmin();

InvalidTreasury

error InvalidTreasury();

InvalidToken

error InvalidToken();

InvalidOracle

error InvalidOracle();

InvalidVault

error InvalidVault();

AlreadyInitialized

error AlreadyInitialized();

NotInitialized

error NotInitialized();

AlreadyActive

error AlreadyActive();

NotActive

error NotActive();

AlreadyPaused

error AlreadyPaused();

NotPaused

error NotPaused();

BelowThreshold

error BelowThreshold();

NoChangeDetected

error NoChangeDetected();

DivisionByZero

error DivisionByZero();

MultiplicationOverflow

error MultiplicationOverflow();

PercentageTooHigh

error PercentageTooHigh();

InvalidParameter

error InvalidParameter();

InvalidCondition

error InvalidCondition();

ETHTransferFailed

error ETHTransferFailed();

TokenTransferFailed

error TokenTransferFailed();

CannotSendToZero

error CannotSendToZero();

NoETHToRecover

error NoETHToRecover();

NoTokensToRecover

error NoTokensToRecover();

CannotRecoverOwnToken

error CannotRecoverOwnToken();

EmergencyModeActive

error EmergencyModeActive();

HoldingPeriodNotMet

error HoldingPeriodNotMet();

InvalidPrice

error InvalidPrice();

InsufficientCollateralization

error InsufficientCollateralization();

TooManyPositions

error TooManyPositions();

PositionNotActive

error PositionNotActive();

LiquidationCooldown

error LiquidationCooldown();

InvalidYieldShift

error InvalidYieldShift();

AdjustmentSpeedTooHigh

error AdjustmentSpeedTooHigh();

TargetRatioTooHigh

error TargetRatioTooHigh();

InvalidRatio

error InvalidRatio();

NotGovernance

error NotGovernance();

NotEmergency

error NotEmergency();

NotEmergencyRole

error NotEmergencyRole();

NotLiquidator

error NotLiquidator();

NotLiquidatorRole

error NotLiquidatorRole();

NotHedger

error NotHedger();

NotVaultManager

error NotVaultManager();

NotYieldManager

error NotYieldManager();

InsufficientYield

error InsufficientYield();

InvalidShiftRange

error InvalidShiftRange();

YieldBelowThreshold

error YieldBelowThreshold();

YieldNotAvailable

error YieldNotAvailable();

YieldDistributionFailed

error YieldDistributionFailed();

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();

LockTimeTooShort

error LockTimeTooShort();

LockTimeTooLong

error LockTimeTooLong();

RateLimitTooHigh

error RateLimitTooHigh();

InvalidOraclePrice

error InvalidOraclePrice();

YieldClaimFailed

error YieldClaimFailed();

InvalidThreshold

error InvalidThreshold();

NotWhitelisted

error NotWhitelisted();

InsufficientVotingPower

error InsufficientVotingPower();

NotInLiquidationMode

error NotInLiquidationMode();

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

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)

validateDuration

Validates that a duration is within valid range

Reverts with HoldingPeriodNotMet if too short, AboveLimit if too long

Notes:

  • security: Pure; no state change

  • validation: Reverts if duration out of [minDuration, maxDuration]

  • state-changes: None

  • events: None

  • errors: HoldingPeriodNotMet, AboveLimit

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateDuration(uint256 duration, uint256 minDuration, uint256 maxDuration) internal pure;

Parameters

NameTypeDescription
durationuint256The duration to validate
minDurationuint256The minimum allowed duration
maxDurationuint256The maximum allowed duration

validatePrice

Validates that a price is valid (greater than zero)

Reverts with InvalidPrice if price is zero

Notes:

  • security: Pure; no state change

  • validation: Reverts if price is zero

  • state-changes: None

  • events: None

  • errors: InvalidPrice

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validatePrice(uint256 price) internal pure;

Parameters

NameTypeDescription
priceuint256The price to validate

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

validateNotContract

Validates that an address is not a contract (for security)

Prevents sending funds to potentially malicious contracts

Notes:

  • security: View; checks extcodesize

  • validation: Reverts if addr has code

  • state-changes: None

  • events: None

  • errors: InvalidTreasury, InvalidAddress

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateNotContract(address addr, string memory errorType) internal view;

Parameters

NameTypeDescription
addraddressThe address to validate
errorTypestringThe type of error to throw if validation fails

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

validateSlippage

Validates slippage protection for token swaps/trades

Reverts with InvalidParameter if slippage exceeds tolerance

Notes:

  • security: Pure; no state change

  • validation: Reverts if received below expected minus tolerance

  • state-changes: None

  • events: None

  • errors: InvalidParameter

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateSlippage(uint256 received, uint256 expected, uint256 tolerance) internal pure;

Parameters

NameTypeDescription
receiveduint256The actual amount received
expecteduint256The expected amount
toleranceuint256The slippage tolerance in basis points

validateThresholdValue

Validates that a value meets minimum threshold requirements

Reverts with BelowThreshold if value is below minimum

Notes:

  • security: Pure; no state change

  • validation: Reverts if value < threshold

  • state-changes: None

  • events: None

  • errors: BelowThreshold

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateThresholdValue(uint256 value, uint256 threshold) internal pure;

Parameters

NameTypeDescription
valueuint256The value to validate
thresholduint256The minimum required threshold

validateFee

Validates fee amount against maximum allowed fee

Reverts with InvalidParameter if fee exceeds maximum

Notes:

  • security: Pure; no state change

  • validation: Reverts if fee > maxFee

  • state-changes: None

  • events: None

  • errors: InvalidParameter

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateFee(uint256 fee, uint256 maxFee) internal pure;

Parameters

NameTypeDescription
feeuint256The fee amount to validate
maxFeeuint256The maximum allowed fee

validateThreshold

Validates threshold value against maximum limit

Reverts with InvalidParameter if threshold exceeds maximum

Notes:

  • security: Pure; no state change

  • validation: Reverts if threshold > maxThreshold

  • state-changes: None

  • events: None

  • errors: InvalidParameter

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function validateThreshold(uint256 threshold, uint256 maxThreshold) internal pure;

Parameters

NameTypeDescription
thresholduint256The threshold value to validate
maxThresholduint256The maximum allowed threshold

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

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

GovernanceErrorLibrary

Git Source

Title: GovernanceErrorLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Governance-specific errors for QTIToken governance system

Main characteristics:

  • Errors specific to governance operations
  • Voting and proposal management errors
  • Timelock and execution errors
  • MEV protection errors

Note: security-contact: team@quantillon.money

Errors

InsufficientVotingPower

error InsufficientVotingPower();

ProposalNotFound

error ProposalNotFound();

VotingNotActive

error VotingNotActive();

ProposalThresholdNotMet

error ProposalThresholdNotMet();

ProposalExecutionFailed

error ProposalExecutionFailed();

ProposalAlreadyScheduled

error ProposalAlreadyScheduled();

ProposalNotScheduled

error ProposalNotScheduled();

InvalidExecutionHash

error InvalidExecutionHash();

ExecutionTimeNotReached

error ExecutionTimeNotReached();

InvalidDescription

error InvalidDescription();

ExpiredDeadline

error ExpiredDeadline();

InvalidRebalancing

error InvalidRebalancing();

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

Errors

FlashLoanAttackDetected

error FlashLoanAttackDetected();

InvalidPosition

error InvalidPosition();

InvalidHedger

error InvalidHedger();

MaxPositionsPerTx

error MaxPositionsPerTx();

AlreadyWhitelisted

error AlreadyWhitelisted();

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();

PendingRewardsExceedMaximum

error PendingRewardsExceedMaximum();

InvalidLeverage

error InvalidLeverage();

LeverageTooHigh

error LeverageTooHigh();

LeverageTooLow

error LeverageTooLow();

MaxLeverageExceeded

error MaxLeverageExceeded();

MarginTooLow

error MarginTooLow();

MarginRatioTooLow

error MarginRatioTooLow();

MarginRatioTooHigh

error MarginRatioTooHigh();

MarginInsufficient

error MarginInsufficient();

MarginLimitExceeded

error MarginLimitExceeded();

PositionNotFound

error PositionNotFound();

PositionOwnerMismatch

error PositionOwnerMismatch();

PositionAlreadyClosed

error PositionAlreadyClosed();

PositionClosureRestricted

error PositionClosureRestricted();

PositionHasActiveFill

error PositionHasActiveFill();

InsufficientHedgerCapacity

error InsufficientHedgerCapacity();

NoActiveHedgerLiquidity

error NoActiveHedgerLiquidity();

HedgerHasActivePosition

error HedgerHasActivePosition();

MinHoldPeriodNotElapsed

error MinHoldPeriodNotElapsed();

EntryFeeTooHigh

error EntryFeeTooHigh();

ExitFeeTooHigh

error ExitFeeTooHigh();

MarginFeeTooHigh

error MarginFeeTooHigh();

YieldFeeTooHigh

error YieldFeeTooHigh();

HedgerPoolLogicLibrary

Git Source

Title: HedgerPoolLogicLibrary

Author: Quantillon Labs

Logic functions for HedgerPool to reduce contract size

Core P&L Calculation Formulas:

  1. TOTAL UNREALIZED P&L (mark-to-market of current position): totalUnrealizedPnL = FilledVolume - (QEUROBacked × OraclePrice / 1e30)
  • Positive when price drops (hedger profits from short EUR position)
  • Negative when price rises (hedger loses from short EUR position)
  1. NET UNREALIZED P&L (after accounting for realized portions): netUnrealizedPnL = totalUnrealizedPnL - realizedPnL
  • Used when margin has been adjusted by realized P&L during redemptions
  • Prevents double-counting since margin already reflects realized P&L
  1. EFFECTIVE MARGIN (true economic value of position): effectiveMargin = margin + netUnrealizedPnL
  • Represents what the hedger would have if position closed now
  • Used for collateralization checks and available collateral calculations
  1. LIQUIDATION MODE (CR ≤ 101%): In liquidation mode, the entire hedger margin is considered at risk. unrealizedPnL = -margin, meaning effectiveMargin = 0

Functions

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. To get NET unrealized P&L (after partial redemptions), subtract realizedPnL from this value.

Notes:

  • security: No security validations required for pure function

  • validation: Validates filledVolume and currentPrice are non-zero

  • 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. netUnrealizedPnL = totalUnrealizedPnL - realizedPnL (margin already reflects realized P&L, so we use net unrealized to avoid double-counting)
  3. effectiveMargin = margin + netUnrealizedPnL
  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%)
realizedPnLint128Cumulative realized P&L from partial redemptions (6 decimals, signed)
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. netUnrealizedPnL = totalUnrealizedPnL - realizedPnL (margin already reflects realized P&L, so we use net unrealized to avoid double-counting)
  3. effectiveMargin = margin + netUnrealizedPnL
  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)
realizedPnLint128Cumulative realized P&L from partial redemptions (6 decimals, signed)

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;
}

IViewOracle

Git Source

Functions

getEurUsdPrice

Returns EUR/USD oracle price and validity flag

Minimal read-only oracle view interface used by optimization helpers.

Notes:

  • security: Read-only oracle accessor

  • validation: Implementer should guarantee returned values follow protocol expectations

  • state-changes: None

  • events: None

  • errors: Implementation-defined

  • reentrancy: Not applicable - view function

  • access: External view interface method

  • oracle: Primary oracle read dependency

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

Returns

NameTypeDescription
priceuint256EUR/USD price in 18 decimals
isValidboolWhether the reported price is valid

HedgerPoolOptimizationLibrary

Git Source

Title: HedgerPoolOptimizationLibrary

Author: Quantillon Labs

Library for HedgerPool data packing, validation, and utility functions

Extracts utility functions from HedgerPool to reduce contract size

Functions

packPositionOpenData

Packs position open data into a single bytes32 for gas efficiency

Encodes position size, margin, leverage, and entry price into a compact format

Notes:

  • security: No security implications - pure data packing 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 packPositionOpenData(uint256 positionSize, uint256 margin, uint256 leverage, uint256 entryPrice)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
positionSizeuint256Size of the position in USDC
marginuint256Margin amount for the position
leverageuint256Leverage multiplier for the position
entryPriceuint256Price at which the position was opened

Returns

NameTypeDescription
<none>bytes32Packed data as bytes32

packPositionCloseData

Packs position close data into a single bytes32 for gas efficiency

Encodes exit price, PnL, and timestamp into a compact format

Notes:

  • security: No security implications - pure data packing 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 packPositionCloseData(uint256 exitPrice, int256 pnl, uint256 timestamp) internal pure returns (bytes32);

Parameters

NameTypeDescription
exitPriceuint256Price at which the position was closed
pnlint256Profit or loss from the position (can be negative)
timestampuint256Timestamp when the position was closed

Returns

NameTypeDescription
<none>bytes32Packed data as bytes32

packMarginData

Packs margin data into a single bytes32 for gas efficiency

Encodes margin amount, new margin ratio, and operation type

Notes:

  • security: No security implications - pure data packing 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 packMarginData(uint256 marginAmount, uint256 newMarginRatio, bool isAdded)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
marginAmountuint256Amount of margin added or removed
newMarginRatiouint256New margin ratio after the operation
isAddedboolTrue if margin was added, false if removed

Returns

NameTypeDescription
<none>bytes32Packed data as bytes32

packLiquidationData

Packs liquidation data into a single bytes32 for gas efficiency

Encodes liquidation reward and remaining margin

Notes:

  • security: No security implications - pure data packing 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 packLiquidationData(uint256 liquidationReward, uint256 remainingMargin) internal pure returns (bytes32);

Parameters

NameTypeDescription
liquidationRewarduint256Reward paid to the liquidator
remainingMarginuint256Margin remaining after liquidation

Returns

NameTypeDescription
<none>bytes32Packed data as bytes32

packRewardData

Packs reward data into a single bytes32 for gas efficiency

Encodes interest differential, yield shift rewards, and total rewards

Notes:

  • security: No security implications - pure data packing 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 packRewardData(uint256 interestDifferential, uint256 yieldShiftRewards, uint256 totalRewards)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
interestDifferentialuint256Interest rate differential between EUR and USD
yieldShiftRewardsuint256Rewards from yield shifting operations
totalRewardsuint256Total rewards accumulated

Returns

NameTypeDescription
<none>bytes32Packed data as bytes32

validateRole

Validates that the caller has the required role

Internal function to check role-based access control

Notes:

  • security: Prevents unauthorized access to protected functions

  • validation: Ensures proper role-based access control

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: Throws NotAuthorized if caller lacks required role

  • reentrancy: Not applicable - view function

  • access: External function with role validation

  • oracle: No oracle dependencies

function validateRole(bytes32 role, address contractInstance) external view;

Parameters

NameTypeDescription
rolebytes32The role to validate against
contractInstanceaddressThe contract instance to check roles on

validatePositionClosureSafety

Validates that closing a position won't cause protocol undercollateralization

Checks if closing the position would make the protocol undercollateralized for QEURO minting

Notes:

  • security: Prevents protocol undercollateralization from position closures

  • validation: Ensures protocol remains properly collateralized

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - returns boolean result

  • reentrancy: Not applicable - view function

  • access: External function

  • oracle: No oracle dependencies

function validatePositionClosureSafety(uint256 positionMargin, address vaultAddress)
    external
    view
    returns (bool isValid);

Parameters

NameTypeDescription
positionMarginuint256The margin amount of the position being closed
vaultAddressaddressAddress of the vault contract

Returns

NameTypeDescription
isValidboolTrue if position can be safely closed

_getProtocolData

Gets protocol collateralization data

Internal function to reduce stack depth

Notes:

  • security: Uses staticcall for safe external contract interaction

  • validation: Validates call success and data length before decoding

  • state-changes: No state changes, view function

  • events: No events emitted

  • errors: Returns default values on call failures

  • reentrancy: No reentrancy risk, view function

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _getProtocolData(address vaultAddress)
    internal
    view
    returns (bool isCollateralized, uint256 currentTotalMargin, uint256 minCollateralizationRatio);

Parameters

NameTypeDescription
vaultAddressaddressAddress of the vault contract

Returns

NameTypeDescription
isCollateralizedboolWhether protocol is currently collateralized
currentTotalMarginuint256Current total margin in the protocol
minCollateralizationRatiouint256Minimum collateralization ratio for minting

_hasQEUROMinted

Checks if QEURO has been minted

Internal function to reduce stack depth

Notes:

  • security: Uses staticcall for safe external contract interaction

  • validation: Validates call success and data length before decoding

  • state-changes: No state changes, view function

  • events: No events emitted

  • errors: Returns false on call failures

  • reentrancy: No reentrancy risk, view function

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _hasQEUROMinted(address vaultAddress) internal view returns (bool hasMinted);

Parameters

NameTypeDescription
vaultAddressaddressAddress of the vault contract

Returns

NameTypeDescription
hasMintedboolWhether QEURO has been minted (totalSupply > 0)

_validateClosureWithUserDeposits

Validates closure with user deposits

Internal function to reduce stack depth

Notes:

  • security: Validates protocol remains collateralized after closure

  • validation: Ensures closure doesn't violate collateralization requirements

  • state-changes: No state changes, view function

  • events: No events emitted

  • errors: No custom errors, returns boolean result

  • reentrancy: No reentrancy risk, view function

  • access: Internal function, no access control needed

  • oracle: No oracle dependencies

function _validateClosureWithUserDeposits(
    address vaultAddress,
    uint256 positionMargin,
    uint256 currentTotalMargin,
    uint256 minCollateralizationRatio
) internal view returns (bool isValid);

Parameters

NameTypeDescription
vaultAddressaddressAddress of the vault contract
positionMarginuint256Margin for the position being closed
currentTotalMarginuint256Current total margin in the protocol
minCollateralizationRatiouint256Minimum collateralization ratio for minting

Returns

NameTypeDescription
isValidboolWhether the position can be safely closed

getValidOraclePrice

Gets a valid EUR/USD price from the oracle

Retrieves and validates price data from the oracle contract

Notes:

  • security: Ensures oracle price data is valid before use

  • validation: Validates oracle response format and data

  • state-changes: No state changes - view function

  • events: No events emitted

  • errors: No errors thrown - returns boolean result

  • reentrancy: Not applicable - view function

  • access: External function

  • oracle: Depends on oracle contract for price data

function getValidOraclePrice(address oracleAddress) external view returns (uint256 price, bool isValid);

Parameters

NameTypeDescription
oracleAddressaddressAddress of the oracle contract

Returns

NameTypeDescription
priceuint256Valid EUR/USD price from oracle
isValidboolTrue if price is valid

HedgerPoolRedeemMathLibrary

Git Source

Title: HedgerPoolRedeemMathLibrary

Externalized math helpers for redemption and realized PnL transitions

Functions

calculateRedeemPnL

Computes realized PnL delta for a redemption share.

Derives the realized PnL portion corresponding to qeuroAmount being redeemed from a position with currentQeuroBacked, using filled volume and mark price. Works by:

  1. Converting currentQeuroBacked to USDC notionals using price.
  2. Computing total unrealized PnL relative to filledBefore.
  3. Subtracting previousRealizedPnL to get net unrealized.
  4. Allocating a proportional share of that PnL to qeuroAmount.

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).
previousRealizedPnLint128Previously realized PnL stored on the position (signed, 128-bit).

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

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

validatePendingRewards

Validates pending rewards against maximum accumulation limit

Prevents excessive reward accumulation that could cause overflow

Notes:

  • security: Prevents reward overflow that could cause system issues

  • validation: Ensures pending rewards stay within accumulation limits

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws PendingRewardsExceedMaximum if rewards exceed limit

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validatePendingRewards(uint256 newRewards, uint256 maxRewards) internal pure;

Parameters

NameTypeDescription
newRewardsuint256The new total pending rewards amount
maxRewardsuint256Maximum allowed pending rewards

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

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

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

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

State Variables

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

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

processBatchLocks

Process batch locks and calculate totals

Processes batch lock operations and calculates total voting power and amounts

Notes:

  • security: Prevents overflow in batch calculations

  • 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 processBatchLocks(
    uint256[] calldata amounts,
    uint256[] calldata lockTimes,
    uint256 currentTimestamp,
    uint256 existingUnlockTime
)
    external
    pure
    returns (
        uint256 totalNewVotingPower,
        uint256 totalNewAmount,
        uint256 finalUnlockTime,
        uint256 finalLockTime,
        uint256[] memory veQTIAmounts
    );

Parameters

NameTypeDescription
amountsuint256[]Array of QTI amounts to lock
lockTimesuint256[]Array of lock durations
currentTimestampuint256Current timestamp
existingUnlockTimeuint256Existing unlock time if already locked

Returns

NameTypeDescription
totalNewVotingPoweruint256Total new voting power from all locks
totalNewAmountuint256Total new amount locked
finalUnlockTimeuint256Final unlock time after all locks
finalLockTimeuint256Final lock time
veQTIAmountsuint256[]Array of calculated voting power amounts

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
}

TimeProvider

Git Source

Inherits: Initializable, AccessControlUpgradeable, UUPSUpgradeable

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

State Variables

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

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

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

Errors

MintingDisabled

error MintingDisabled();

BlacklistedAddress

error BlacklistedAddress();

CannotRecoverQEURO

error CannotRecoverQEURO();

CannotRecoverQTI

error CannotRecoverQTI();

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

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

function validateBurn(address from, uint256 amount, uint256 balance) internal pure;

Parameters

NameTypeDescription
fromaddressAddress to burn from
amountuint256Amount to burn
balanceuint256Current balance

TokenValidationLibrary

Git Source

Title: TokenValidationLibrary

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Token-specific validation functions for Quantillon Protocol

Main characteristics:

  • Validation functions specific to token operations
  • Fee and threshold validations
  • Oracle price validations
  • Treasury address validations

Note: security-contact: team@quantillon.money

Functions

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 AboveLimit 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

validateThreshold

Validates threshold value against maximum limit

Used for liquidation thresholds, margin ratios, etc.

Notes:

  • security: Prevents thresholds that could destabilize the system

  • validation: Ensures thresholds stay within acceptable bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws AboveLimit if threshold exceeds maximum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateThreshold(uint256 threshold, uint256 maxThreshold) internal pure;

Parameters

NameTypeDescription
thresholduint256The threshold value to validate
maxThresholduint256The maximum allowed threshold

validateThresholdValue

Validates that a value meets minimum threshold requirements

Used for minimum deposits, stakes, withdrawals, etc.

Notes:

  • security: Prevents operations below minimum thresholds

  • validation: Ensures values meet business requirements

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws BelowThreshold if value is below minimum

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateThresholdValue(uint256 value, uint256 threshold) internal pure;

Parameters

NameTypeDescription
valueuint256The value to validate
thresholduint256The minimum required threshold

validateOraclePrice

Validates oracle price data integrity

Ensures oracle price is valid before using in calculations

Notes:

  • security: Prevents use of invalid oracle data that could cause financial losses

  • validation: Ensures oracle price data is valid and recent

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws InvalidParameter if oracle price is invalid

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: Validates oracle price data integrity

function validateOraclePrice(bool isValid) internal pure;

Parameters

NameTypeDescription
isValidboolWhether the oracle price is valid and recent

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

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

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

State Variables

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

REWARD_CLAIM_COOLDOWN

uint256 public constant REWARD_CLAIM_COOLDOWN = 1 days

Functions

_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

calculateTotalStakingRewards

Calculates total staking rewards for a user

Calculates total rewards across all active stakes for a user

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 calculateTotalStakingRewards(StakeInfo[] memory userStakes, uint256 stakingAPY, uint256 currentTime)
    external
    pure
    returns (uint256 totalRewards);

Parameters

NameTypeDescription
userStakesStakeInfo[]Array of user stakes
stakingAPYuint256Staking APY in basis points
currentTimeuint256Current timestamp

Returns

NameTypeDescription
totalRewardsuint256Total rewards for all stakes

validateStakeParameters

Validates stake parameters

Ensures stake parameters are within acceptable bounds

Notes:

  • security: Prevents invalid stake parameters from being processed

  • validation: Validates amounts, durations, and user limits

  • 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 validateStakeParameters(uint256 amount, uint256 duration, UserStakingData memory userStakingData)
    external
    pure;

Parameters

NameTypeDescription
amountuint256Stake amount
durationuint256Stake duration
userStakingDataUserStakingDataUser's current staking data

validateUnstakeParameters

Validates unstake parameters

Ensures unstake operations meet minimum requirements

Notes:

  • security: Prevents premature unstaking and enforces cooldowns

  • validation: Validates stake status and timing requirements

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws various validation errors for invalid unstake attempts

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function validateUnstakeParameters(StakeInfo memory stakeInfo, uint256 currentTime) external pure;

Parameters

NameTypeDescription
stakeInfoStakeInfoStake information
currentTimeuint256Current timestamp

calculateUnstakePenalty

Calculates unstake penalty

Calculates penalty based on stake duration to discourage early unstaking

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 calculateUnstakePenalty(StakeInfo memory stakeInfo, uint256 currentTime)
    external
    pure
    returns (uint256 penalty);

Parameters

NameTypeDescription
stakeInfoStakeInfoStake information
currentTimeuint256Current timestamp

Returns

NameTypeDescription
penaltyuint256Penalty percentage in basis points

calculateDepositAPY

Calculates deposit APY based on pool metrics

Adjusts deposit APY based on staking ratio to incentivize optimal behavior

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 calculateDepositAPY(uint256 totalDeposits, uint256 totalStaked, uint256 baseAPY)
    external
    pure
    returns (uint256 depositAPY);

Parameters

NameTypeDescription
totalDepositsuint256Total pool deposits
totalStakeduint256Total staked amount
baseAPYuint256Base APY in basis points

Returns

NameTypeDescription
depositAPYuint256Calculated deposit APY

calculateStakingAPY

Calculates staking APY based on pool metrics

Adjusts staking APY based on staking ratio to incentivize optimal behavior

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 calculateStakingAPY(uint256 totalDeposits, uint256 totalStaked, uint256 baseAPY)
    external
    pure
    returns (uint256 stakingAPY);

Parameters

NameTypeDescription
totalDepositsuint256Total pool deposits
totalStakeduint256Total staked amount
baseAPYuint256Base APY in basis points

Returns

NameTypeDescription
stakingAPYuint256Calculated staking APY

calculateDynamicFee

Calculates fee for deposit/withdrawal

Adjusts fees based on pool utilization to manage liquidity

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 calculateDynamicFee(uint256 amount, uint256 baseFee, uint256 poolUtilization)
    external
    pure
    returns (uint256 fee);

Parameters

NameTypeDescription
amountuint256Transaction amount
baseFeeuint256Base fee in basis points
poolUtilizationuint256Pool utilization ratio

Returns

NameTypeDescription
feeuint256Calculated fee amount

calculatePoolMetrics

Calculates pool metrics

Packs pool metrics into a single uint256 for gas efficiency

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 calculatePoolMetrics(uint256 totalDeposits, uint256 totalStaked, uint256 totalUsers)
    external
    pure
    returns (uint256 metrics);

Parameters

NameTypeDescription
totalDepositsuint256Total pool deposits
totalStakeduint256Total staked amount
totalUsersuint256Total number of users

Returns

NameTypeDescription
metricsuint256Packed pool metrics

unpackPoolMetrics

Unpacks pool metrics

Unpacks pool metrics from a single uint256 for gas efficiency

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 unpackPoolMetrics(uint256 metrics)
    external
    pure
    returns (uint256 stakingRatio, uint256 averageDeposit, uint256 totalUsers);

Parameters

NameTypeDescription
metricsuint256Packed pool metrics

Returns

NameTypeDescription
stakingRatiouint256Staking ratio in basis points
averageDeposituint256Average deposit per user
totalUsersuint256Total number of users

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;
}

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
  • Collateralization and emergency mode errors
  • Pool health and balance errors
  • Yield distribution errors

Note: security-contact: team@quantillon.money

Errors

PoolNotHealthy

error PoolNotHealthy();

PoolRatioInvalid

error PoolRatioInvalid();

PoolSizeZero

error PoolSizeZero();

PoolImbalance

error PoolImbalance();

CannotRecoverUSDC

error CannotRecoverUSDC();

CannotRecoverAToken

error CannotRecoverAToken();

CannotRecoverCriticalToken

error CannotRecoverCriticalToken(string tokenName);

AavePoolNotHealthy

error AavePoolNotHealthy();

WouldBreachMinimum

error WouldBreachMinimum();

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

State Variables

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

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

mulDivUp

Multiply two numbers and divide by a third, rounding the result up

Ceiling variant of mulDiv. If there is any non-zero remainder after division, the result is increased by 1 to round towards positive infinity.

Notes:

  • security: Uses mulDiv internally for overflow and division-by-zero protection

  • validation: Caller must ensure c is non-zero; reverts via mulDiv otherwise

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Reverts with DivisionByZero or MultiplicationOverflow via mulDiv on invalid inputs

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function mulDivUp(uint256 a, uint256 b, uint256 c) internal pure returns (uint256 result);

Parameters

NameTypeDescription
auint256First multiplicand
buint256Second multiplicand
cuint256Divisor

Returns

NameTypeDescription
resultuint256a * b / c, rounded up when there is a remainder

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

min

Calculate minimum value between two numbers

Returns the smaller of a and b

Notes:

  • security: Pure; no overflow

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function min(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256First number
buint256Second number

Returns

NameTypeDescription
<none>uint256Minimum value

max

Calculate maximum value between two numbers

Returns the larger of a and b

Notes:

  • security: Pure; no overflow

  • validation: None

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function max(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256First number
buint256Second number

Returns

NameTypeDescription
<none>uint256Maximum value

eurToUsd

Convert EUR amount to USD using exchange rate

usdAmount = eurAmount * eurUsdRate / PRECISION

Notes:

  • security: Uses mulDiv; no division by zero if rate > 0

  • validation: Caller must ensure eurUsdRate > 0

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: Rate passed in; no live oracle

function eurToUsd(uint256 eurAmount, uint256 eurUsdRate) internal pure returns (uint256 usdAmount);

Parameters

NameTypeDescription
eurAmountuint256Amount in EUR (18 decimals)
eurUsdRateuint256EUR/USD exchange rate (18 decimals)

Returns

NameTypeDescription
usdAmountuint256Amount in USD (18 decimals)

usdToEur

Convert USD amount to EUR using exchange rate

eurAmount = usdAmount * PRECISION / eurUsdRate

Notes:

  • security: Uses mulDiv; reverts if eurUsdRate is zero

  • validation: Caller must ensure eurUsdRate > 0

  • state-changes: None

  • events: None

  • errors: DivisionByZero if eurUsdRate is 0

  • reentrancy: No external calls

  • access: Internal library

  • oracle: Rate passed in; no live oracle

function usdToEur(uint256 usdAmount, uint256 eurUsdRate) internal pure returns (uint256 eurAmount);

Parameters

NameTypeDescription
usdAmountuint256Amount in USD (18 decimals)
eurUsdRateuint256EUR/USD exchange rate (18 decimals)

Returns

NameTypeDescription
eurAmountuint256Amount in EUR (18 decimals)

calculateCollateralRatio

Calculate collateralization ratio

Returns type(uint256).max when debtValue is zero (infinite ratio)

Notes:

  • security: Pure; no overflow for typical values

  • validation: debtValue 0 returns max

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function calculateCollateralRatio(uint256 collateralValue, uint256 debtValue)
    internal
    pure
    returns (uint256 ratio);

Parameters

NameTypeDescription
collateralValueuint256Total collateral value in USD
debtValueuint256Total debt value in USD

Returns

NameTypeDescription
ratiouint256Collateralization ratio in 18 decimals (e.g., 1.5e18 = 150%)

calculateYieldDistribution

Calculate yield distribution between users and hedgers

Reverts with InvalidParameter if yieldShiftBps exceeds BASIS_POINTS

Notes:

  • security: Pure; hedgerYield + userYield = totalYield

  • validation: yieldShiftBps <= BASIS_POINTS

  • state-changes: None

  • events: None

  • errors: InvalidParameter if yieldShiftBps > BASIS_POINTS

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function calculateYieldDistribution(uint256 totalYield, uint256 yieldShiftBps)
    internal
    pure
    returns (uint256 userYield, uint256 hedgerYield);

Parameters

NameTypeDescription
totalYielduint256Total yield generated
yieldShiftBpsuint256Yield shift percentage in basis points (0-10000)

Returns

NameTypeDescription
userYielduint256Yield allocated to QEURO users
hedgerYielduint256Yield allocated to hedgers

isWithinTolerance

Check if a value is within a certain percentage of another value

difference <= percentageOf(larger, toleranceBps)

Notes:

  • security: Pure; uses percentageOf

  • validation: toleranceBps <= MAX_PERCENTAGE implied by percentageOf

  • state-changes: None

  • events: None

  • errors: None

  • reentrancy: No external calls

  • access: Internal library

  • oracle: None

function isWithinTolerance(uint256 value1, uint256 value2, uint256 toleranceBps) internal pure returns (bool);

Parameters

NameTypeDescription
value1uint256First value
value2uint256Second value
toleranceBpsuint256Tolerance in basis points

Returns

NameTypeDescription
<none>boolisWithinTolerance Whether values are within tolerance

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

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

calculateUserAllocation

Calculates user allocation percentage

Calculates user allocation based on 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 yieldShift) external pure returns (uint256 userAllocation);

Parameters

NameTypeDescription
yieldShiftuint256Current yield shift percentage

Returns

NameTypeDescription
userAllocationuint256User allocation percentage

calculateHedgerAllocation

Calculates hedger allocation percentage

Calculates hedger allocation based on 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 yieldShift) external pure returns (uint256 hedgerAllocation);

Parameters

NameTypeDescription
yieldShiftuint256Current yield shift percentage

Returns

NameTypeDescription
hedgerAllocationuint256Hedger allocation percentage

calculatePoolTWAP

Calculates TWAP for pool sizes

Calculates time-weighted average price for pool sizes

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 calculatePoolTWAP(uint256[] memory snapshots)
    external
    pure
    returns (uint256 userPoolTWAP, uint256 hedgerPoolTWAP);

Parameters

NameTypeDescription
snapshotsuint256[]Array of pool snapshots

Returns

NameTypeDescription
userPoolTWAPuint256TWAP for user pool size
hedgerPoolTWAPuint256TWAP for hedger pool size

calculateYieldDistribution

Calculates yield distribution amounts

Calculates yield distribution between users and hedgers

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 calculateYieldDistribution(uint256 totalYield, uint256 userAllocation, uint256 hedgerAllocation)
    external
    pure
    returns (uint256 userYield, uint256 hedgerYield);

Parameters

NameTypeDescription
totalYielduint256Total yield to distribute
userAllocationuint256User allocation percentage
hedgerAllocationuint256Hedger allocation percentage

Returns

NameTypeDescription
userYielduint256User yield amount
hedgerYielduint256Hedger yield amount

validateYieldShiftParams

Validates yield shift parameters

Ensures yield shift parameters are within valid bounds

Notes:

  • security: Prevents invalid yield shift parameters

  • validation: Validates all parameters are within acceptable bounds

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws require statements for invalid parameters

  • reentrancy: Not applicable - pure function

  • access: Public function

  • oracle: No oracle dependencies

function validateYieldShiftParams(
    uint256 baseYieldShift,
    uint256 maxYieldShift,
    uint256 adjustmentSpeed,
    uint256 targetPoolRatio
) external pure;

Parameters

NameTypeDescription
baseYieldShiftuint256Base yield shift
maxYieldShiftuint256Maximum yield shift
adjustmentSpeeduint256Adjustment speed
targetPoolRatiouint256Target pool ratio

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

State Variables

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

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: No errors thrown - view function

  • 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: No errors thrown - view function

  • 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

Calculate eligible user pool size excluding recent deposits

Only counts deposits older than MIN_HOLDING_PERIOD

Notes:

  • security: Prevents flash deposit attacks by excluding recent deposits

  • 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 calculateEligibleUserPoolSize(uint256 totalUserPoolSize, uint256 currentTime, uint256 lastUpdateTime)
    external
    pure
    returns (uint256 eligibleSize);

Parameters

NameTypeDescription
totalUserPoolSizeuint256Current total user pool size
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
eligibleSizeuint256Eligible pool size for yield calculations

_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

Calculate eligible hedger pool size excluding recent deposits

Only counts deposits older than MIN_HOLDING_PERIOD

Notes:

  • security: Prevents flash deposit attacks by excluding recent deposits

  • 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 calculateEligibleHedgerPoolSize(uint256 totalHedgerPoolSize, uint256 currentTime, uint256 lastUpdateTime)
    external
    pure
    returns (uint256 eligibleSize);

Parameters

NameTypeDescription
totalHedgerPoolSizeuint256Current total hedger 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

Calculate holding period discount based on recent deposit activity

Returns a percentage (in basis points) representing eligible deposits

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 calculateHoldingPeriodDiscount(uint256 currentTime, uint256 lastUpdateTime)
    external
    pure
    returns (uint256 discountBps);

Parameters

NameTypeDescription
currentTimeuint256Current timestamp
lastUpdateTimeuint256Last update timestamp

Returns

NameTypeDescription
discountBpsuint256Discount in basis points (10000 = 100%)

_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

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

validateSlippage

Validates slippage protection for token swaps/trades

Ensures received amount is within acceptable tolerance of expected

Notes:

  • security: Prevents excessive slippage attacks in yield operations

  • validation: Ensures received amount meets minimum expectations

  • state-changes: No state changes - pure function

  • events: No events emitted

  • errors: Throws ExcessiveSlippage if slippage exceeds tolerance

  • reentrancy: Not applicable - pure function

  • access: Internal library function

  • oracle: No oracle dependencies

function validateSlippage(uint256 received, uint256 expected, uint256 tolerance) internal pure;

Parameters

NameTypeDescription
receiveduint256The actual amount received
expecteduint256The expected amount
toleranceuint256The slippage tolerance in basis points

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

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

State Variables

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

ORACLE_MANAGER_ROLE

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

eurUsdPriceFeed

AggregatorV3Interface public eurUsdPriceFeed

usdcUsdPriceFeed

AggregatorV3Interface public usdcUsdPriceFeed

treasury

address public treasury

originalAdmin

address private originalAdmin

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

lastValidEurUsdPrice

uint256 public lastValidEurUsdPrice

lastValidUsdcUsdPrice

uint256 public lastValidUsdcUsdPrice

lastPriceUpdateBlock

uint256 public lastPriceUpdateBlock

MIN_BLOCKS_BETWEEN_UPDATES

uint256 public constant MIN_BLOCKS_BETWEEN_UPDATES = 1

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.

State Variables

USDC

IERC20 public immutable USDC

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

State Variables

EMERGENCY_ROLE

bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE")

ORACLE_MANAGER_ROLE

bytes32 public constant ORACLE_MANAGER_ROLE = keccak256("ORACLE_MANAGER_ROLE")

treasury

address public treasury

originalAdmin

address private originalAdmin

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

lastValidEurUsdPrice

uint256 public lastValidEurUsdPrice

lastValidUsdcUsdPrice

uint256 public lastValidUsdcUsdPrice

lastPriceUpdateBlock

uint256 public lastPriceUpdateBlock

MIN_BLOCKS_BETWEEN_UPDATES

uint256 public constant MIN_BLOCKS_BETWEEN_UPDATES = 1

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

State Variables

_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

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

State Variables

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

BLOCKS_PER_HOUR

Blocks per hour for block-based staleness checks

~12 second blocks on Ethereum, ~2 second blocks on L2s

uint256 public constant BLOCKS_PER_HOUR = 300

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

DEV_MODE_DELAY

MED-1: Minimum delay before a proposed dev-mode change takes effect

uint256 public constant DEV_MODE_DELAY = 48 hours

pendingDevMode

MED-1: Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

MED-1: Timestamp at which pendingDevMode may be applied (0 = no pending proposal)

uint256 public devModePendingAt

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

Functions

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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

_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 of last update
isStalebooltrue if the price is stale
withinBoundsbooltrue if within acceptable bounds

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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: Protected by 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: Protected by reentrancy guard

  • access: Restricted to authorized roles

  • oracle: Requires fresh oracle price data

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: No state changes - view function only

  • events: No events emitted

  • errors: No errors thrown - returns fallback price if invalid

  • reentrancy: Not applicable - view function

  • access: Public - no access restrictions

  • oracle: Requires fresh Chainlink EUR/USD price feed data

function getEurUsdPrice() external view 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

MED-1: 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

MED-1: 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: 0xBCF85224fc0756B9Fa45aA7892E69A2E01D7580D

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

MED-1: 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);

OracleRouter

Git Source

Inherits: IOracle, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable

Title: OracleRouter

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Router contract that allows admin to switch between Chainlink and Stork oracles

Key features:

  • Holds references to both ChainlinkOracle and StorkOracle
  • Routes all IOracle calls to the currently active oracle
  • Admin can switch between oracles via switchOracle()
  • Implements IOracle interface (generic, oracle-agnostic)
  • Protocol contracts use IOracle interface for oracle-agnostic integration

Note: security-contact: team@quantillon.money

State Variables

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")

chainlinkOracle

Chainlink oracle contract reference

IChainlinkOracle public chainlinkOracle

storkOracle

Stork oracle contract reference

IStorkOracle public storkOracle

activeOracle

Currently active oracle type

OracleType public activeOracle

treasury

Treasury address for ETH recovery

address public treasury

Functions

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 ChainlinkOracle and StorkOracle contracts

function initialize(
    address admin,
    address _chainlinkOracle,
    address _storkOracle,
    address _treasury,
    OracleType _defaultOracle
) public initializer;

Parameters

NameTypeDescription
adminaddressAddress with administrator privileges
_chainlinkOracleaddressChainlinkOracle contract address
_storkOracleaddressStorkOracle contract address
_treasuryaddressTreasury address for ETH recovery
_defaultOracleOracleTypeDefault oracle to use (CHAINLINK or STORK)

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 storkOracle 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 STORK)

getOracleAddresses

Gets the addresses of both oracle contracts

Returns chainlinkOracle and storkOracle 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 storkAddress);

Returns

NameTypeDescription
chainlinkAddressaddressAddress of ChainlinkOracle contract
storkAddressaddressAddress of StorkOracle contract

_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 Chainlink and Stork

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 STORK)

updateOracleAddresses

Updates the oracle contract addresses

Validates both addresses; updates chainlinkOracle and storkOracle; emits OracleAddressesUpdated

Notes:

  • security: ORACLE_MANAGER_ROLE only

  • validation: Both addresses not zero

  • state-changes: chainlinkOracle, storkOracle

  • events: OracleAddressesUpdated

  • errors: InvalidOracle if zero

  • reentrancy: No external calls

  • access: ORACLE_MANAGER_ROLE

  • oracle: None

function updateOracleAddresses(address _chainlinkOracle, address _storkOracle)
    external
    onlyRole(ORACLE_MANAGER_ROLE);

Parameters

NameTypeDescription
_chainlinkOracleaddressNew ChainlinkOracle address
_storkOracleaddressNew StorkOracle address

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: May update oracle state

  • events: None

  • errors: Via oracle

  • reentrancy: External call to oracle

  • access: Anyone

  • oracle: Delegates to active oracle

function getEurUsdDetails()
    external
    override
    returns (uint256 currentPrice, uint256 lastValidPrice, uint256 lastUpdate, bool isStale, bool withinBounds);

Returns

NameTypeDescription
currentPriceuint256Current price (may be fallback)
lastValidPriceuint256Last validated price stored
lastUpdateuint256Timestamp of last successful update
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 for Stork oracle - use oracle-specific methods instead

Notes:

  • security: Only Chainlink path; reverts for Stork

  • validation: Via ChainlinkOracle

  • state-changes: Oracle feed addresses

  • events: Via oracle

  • errors: Reverts for Stork

  • 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 newStorkOracle);

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

enum OracleType {
    CHAINLINK,
    STORK
}

SlippageStorage

Git Source

Inherits: ISlippageStorage, Initializable, AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable

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

State Variables

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

_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

TIME_PROVIDER

Shared time provider for deterministic timestamp reads

TimeProvider public immutable TIME_PROVIDER

Functions

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)

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;

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

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

State Variables

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

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

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

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

DEV_MODE_DELAY

MED-1: Minimum delay before a proposed dev-mode change takes effect

uint256 public constant DEV_MODE_DELAY = 48 hours

pendingDevMode

MED-1: Pending dev-mode value awaiting the timelock delay

bool public pendingDevMode

devModePendingAt

MED-1: Timestamp at which pendingDevMode may be applied (0 = no pending proposal)

uint256 public devModePendingAt

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

Functions

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

_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 of last update
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: Protected by 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: 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 EUR/USD price

function getEurUsdPrice() external view 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: Protected by 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: Protected by 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: Protected by 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

MED-1: 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

MED-1: 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

MED-1: 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