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.
| Contract | Address | Network |
|---|---|---|
| QuantillonVault | 0x... | Base Mainnet |
| QEUROToken | 0x... | Base Mainnet |
| QTIToken | 0x... | Base Mainnet |
| UserPool | 0x... | Base Mainnet |
| HedgerPool | 0x... | Base Mainnet |
| stQEUROFactory | 0x... | Base Mainnet |
| stQEUROToken | 0x... | Base Mainnet |
| AaveVault | 0x... | Base Mainnet |
| YieldShift | 0x... | Base Mainnet |
| ChainlinkOracle | 0x... | 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:
_hedgerPooland_userPoolcan be wired later through governance setters._timelockis 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 vaulttotalMinted_: QEURO minted by vault trackertotalDebtValue: USD debt value using live token supply and cached EUR/USDtotalUsdcInExternalVaults_: Principal tracker across all configured external vault adapterstotalUsdcAvailable_: 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 > 0lockTime >= 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 > 0leverage >= 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:
minMarginRatiomaxLeverageminPositionHoldBlocksminMarginAmounteurInterestRateusdInterestRateentryFeeexitFeemarginFeerewardFeeSplit(1e18 = 100%)
configureDependencies(HedgerDependencyConfig cfg)
Batch governance setter for:
treasuryvaultoracleyieldShiftfeeCollector
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 > 0vaultNameuppercase alphanumeric with length1..12- unique
vaultId, unique caller vault, uniquevaultName - 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:
tokenNametokenSymbolvaultName
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 > 0and vault must be registered instQEUROFactoryyieldAmount > 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:
baseYieldShiftmaxYieldShiftadjustmentSpeedtargetPoolRatio
configureDependencies(YieldDependencyConfig cfg)
Batch governance setter for:
userPoolhedgerPoolaaveVaultstQEUROFactorytreasury
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
| Role | Description | Key Functions |
|---|---|---|
DEFAULT_ADMIN_ROLE | Super admin | All administrative functions |
EMERGENCY_ROLE | Emergency operations | Pause/unpause, circuit breaker |
GOVERNANCE_ROLE | Governance operations | Parameter updates, proposals |
VAULT_ROLE | Vault operations | Mint/burn QEURO |
YIELD_MANAGER_ROLE | Yield management | Distribute yield, manage Aave |
COMPLIANCE_ROLE | Compliance operations | Whitelist/blacklist addresses |
LIQUIDATOR_ROLE | Liquidation operations | Liquidate positions |
TIME_MANAGER_ROLE | Time management | Set time offsets |
Constants and Limits
QuantillonVault
MAX_MINT_AMOUNT: 1,000,000 USDCMIN_MINT_AMOUNT: 1 USDCMAX_REDEEM_AMOUNT: 1,000,000 QEUROMIN_REDEEM_AMOUNT: 1 QEURO
QEUROToken
MAX_SUPPLY: 1,000,000,000 QEURO (1B tokens)MIN_PRICE_PRECISION: 2 decimalsMAX_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 veQTIVOTING_PERIOD: 7 days (604,800 seconds)
UserPool
MIN_STAKE_AMOUNT: 100 QEUROMAX_STAKE_AMOUNT: 10,000,000 QEUROUNSTAKE_COOLDOWN: 7 days (604,800 seconds)
HedgerPool
MAX_LEVERAGE: 10xMIN_LEVERAGE: 1xMIN_MARGIN_RATIO: 110% (1.1)LIQUIDATION_THRESHOLD: 105% (1.05)MAX_POSITIONS_PER_HEDGER: 50
AaveVault
MAX_AAVE_EXPOSURE: 80% of total USDCMIN_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
-
Access Control Errors
UnauthorizedAccess()InsufficientRole()InvalidRole()
-
Validation Errors
InvalidAmount()InvalidAddress()InvalidParameter()InvalidTime()
-
Business Logic Errors
InsufficientBalance()InsufficientAllowance()ExceedsLimit()BelowMinimum()
-
Oracle Errors
StalePrice()InvalidPrice()CircuitBreakerActive()
-
Emergency Errors
ContractPaused()EmergencyMode()
Gas Optimization
Best Practices
- Use
viewfunctions for read-only operations - Batch operations when possible
- Cache storage reads in loops
- Use events instead of storage for logging
- Implement proper access control to prevent unauthorized calls
Gas Estimates
| Function | Gas Cost (approx.) |
|---|---|
mintQEURO | 150,000 |
redeemQEURO | 140,000 |
stake | 120,000 |
enterHedgePosition | 200,000 |
exitHedgePosition | 180,000 |
lock | 160,000 |
vote | 100,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.