Quantillon Protocol

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.