Quantillon Protocol

StakingYieldLibrary

Git Source

Title: StakingYieldLibrary

External (linked) library holding the stQEURO yield-distribution split, extracted from QuantillonVault to keep that contract under the EIP-170 24,576-byte runtime limit.

Called via delegatecall from QuantillonVault, so external calls (adapter harvest, USDC transfers) execute in the vault's context (address(this) == vault). The vault performs the stQEURO credit and event emission; this library realizes the yield, computes the hedger / staker / treasury split, and routes the hedger and treasury shares.

Constants

BPS_DENOMINATOR

uint256 private constant BPS_DENOMINATOR = 10000

Functions

setPriority

Replaces the withdrawal priority with unique configured adapter ids.

Prevents duplicate principal accounting in priority-dependent views.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Rejects inactive, duplicate, zero, or unconfigured ids.

  • state-changes: Replaces priority storage.

  • events: RedemptionPriorityUpdated.

  • errors: InvalidVault or ZeroAddress.

  • reentrancy: No external calls.

  • access: Linked library.

  • oracle: None.

function setPriority(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    uint256[] storage priority,
    uint256[] calldata ids
) external;

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active flags.
priorityuint256[]Existing priority storage.
idsuint256[]Requested ids.

configureAdapter

Configures an external adapter while preserving tracked collateral.

Funded replacements require a paused vault, empty old adapter, and funded new adapter.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Rejects disabling funded adapters and unfunded replacements.

  • state-changes: Updates registry and active flag.

  • events: StakingVaultConfigured.

  • errors: InvalidVault, ZeroAddress, InvalidCondition.

  • reentrancy: External adapter calls are view-only.

  • access: Linked library.

  • oracle: None.

function configureAdapter(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    mapping(uint256 => uint256) storage principal,
    uint256 id,
    address next,
    bool enabled,
    bool isPaused
) external;

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active adapter flags.
principalmapping(uint256 => uint256)Tracked principal by vault.
iduint256Vault id.
nextaddressNew adapter.
enabledboolRequested active flag.
isPausedboolVault pause state.

realizeLoss

Records reduced external collateral without changing hedger margin.

The caller deducts the returned loss from aggregate external principal.

Notes:

  • security: Caller enforces governance authorization.

  • validation: Adapter must exist and report less underlying than tracked principal.

  • state-changes: Reduces per-vault principal.

  • events: ExternalVaultLossRealized.

  • errors: InvalidVault or InvalidCondition.

  • reentrancy: View-only adapter call.

  • access: Linked library.

  • oracle: None.

function realizeLoss(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => uint256) storage principal,
    uint256 id
) external returns (uint256 loss);

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
principalmapping(uint256 => uint256)Tracked principal by vault.
iduint256Vault id.

Returns

NameTypeDescription
lossuint256USDC principal loss recognized.

registerToken

Registers and verifies a deterministic per-vault staking token.

Preserves registry binding before the external factory call.

Notes:

  • security: Vault wrapper enforces governance and nonReentrant.

  • validation: Requires a fresh valid binding and matching preview.

  • state-changes: Stores token binding.

  • events: Factory emits registration events; caller emits local registration.

  • errors: InvalidToken, InvalidVault, AlreadyInitialized, InvalidAddress.

  • reentrancy: Caller holds the guard.

  • access: Linked library.

  • oracle: None.

function registerToken(
    mapping(uint256 => address) storage tokens,
    address factory,
    uint256 id,
    string calldata name
) external returns (address token);

Parameters

NameTypeDescription
tokensmapping(uint256 => address)Per-vault staking token registry.
factoryaddressFactory address.
iduint256Vault identifier.
namestringVault name.

Returns

NameTypeDescription
tokenaddressRegistered staking token.

withdrawPrincipal

Sources an exact aggregate payout from priority-ordered adapters.

Requires every adapter to return the exact requested amount and verifies the balance delta. Adapters must absorb any rounding dust internally before returning.

Notes:

  • security: Delegatecalled from guarded vault settlement.

  • validation: Requires exact aggregate liquidity and verifies adapter balance deltas.

  • state-changes: Reduces per-adapter principal; caller reduces aggregate principal.

  • events: UsdcWithdrawnFromExternalVault.

  • errors: InvalidAmount or InsufficientBalance.

  • reentrancy: Caller holds nonReentrant guard.

  • access: Linked library.

  • oracle: None.

function withdrawPrincipal(
    mapping(uint256 => IExternalStakingVault) storage adapters,
    mapping(uint256 => bool) storage active,
    mapping(uint256 => uint256) storage principal,
    uint256[] memory priority,
    uint256 amount,
    IERC20 usdc
) external returns (uint256 withdrawn);

Parameters

NameTypeDescription
adaptersmapping(uint256 => IExternalStakingVault)Adapter registry.
activemapping(uint256 => bool)Active adapter flags.
principalmapping(uint256 => uint256)Per-adapter tracked principal.
priorityuint256[]Ordered source identifiers.
amountuint256Exact USDC deficit to source.
usdcIERC20Collateral token.

Returns

NameTypeDescription
withdrawnuint256Aggregate transferred USDC.

version

Returns the semantic version of this linked library.

On-chain version of the standalone deployed library; bump per semver on any change. See deployments/{chainId}/versions.json for deployed-address provenance.

Notes:

  • security: No security implications - returns a compile-time constant.

  • validation: No input validation required.

  • state-changes: None - pure function.

  • events: None.

  • errors: None.

  • reentrancy: Not applicable - pure function.

  • access: Public - anyone can read the version.

  • oracle: No oracle dependencies.

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

Returns

NameTypeDescription
<none>stringSemantic version string (e.g. "1.0.0").

calculateSplit

Calculate conserved capital-weighted allocations of realized yield.

Floors the hedger base and haircut; residual rounding remains in the user/treasury allocation.

Notes:

  • security: Never deducts principal; allocations sum to yieldUsdc.

  • validation: Haircut cannot exceed 100%.

  • state-changes: None.

  • events: None.

  • errors: AboveLimit for an invalid haircut.

  • reentrancy: No external calls.

  • access: Public library calculation.

  • oracle: Uses caller-supplied economic values.

function calculateSplit(uint256 yieldUsdc, Capital memory c, uint256 haircutBps)
    public
    pure
    returns (Split memory s);

Parameters

NameTypeDescription
yieldUsdcuint256Realized USDC yield.
cCapitalEconomic ownership snapshot.
haircutBpsuint256Percentage of gross staker yield, in basis points.

Returns

NameTypeDescription
sSplitDistribution before existing staking fees.

_params

Resolve the calling vault's configuration before taking a capital snapshot.

Only called by delegatecall entrypoints; external self-calls read public vault getters.

function _params(uint256 vaultId) private view returns (DistributeParams memory p);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
pDistributeParamsValidated configuration.

_snapshot

Snapshot capital and enforce the single-funded-strategy distribution boundary.

Registered token balances include credited unvested QEURO when shareholders exist.

Notes:

  • security: Fails closed on unsupported strategies or invalid oracle/accounting reads.

  • validation: All external principal and all outstanding staking shares must belong to this series.

  • state-changes: Oracle may refresh its price cache.

  • events: Oracle events only.

  • errors: InvalidCondition, InvalidVault, InvalidOraclePrice, or propagated external errors.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Internal library helper.

  • oracle: Fresh validated EUR/USD reference price.

function _snapshot(DistributeParams memory p) private returns (Capital memory c);

Parameters

NameTypeDescription
pDistributeParamsCalling vault configuration.

Returns

NameTypeDescription
cCapitalEconomic ownership before harvest and minting.

previewSplit

Preview the next distribution with the same ownership calculation as execution.

Call through eth_call: the oracle interface can refresh state. Actual realized yield may differ.

Notes:

  • security: Shares execution validation and requires a recipient for nonzero hedger payments.

  • validation: Validates capital, strategy boundary, oracle and recipient.

  • state-changes: Oracle cache only; eth_call persists nothing.

  • events: Oracle events only.

  • errors: Propagates snapshot errors; ZeroAddress for a missing hedger recipient.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Linked library.

  • oracle: Fresh EUR/USD reference price.

function previewSplit(uint256 vaultId) external returns (Split memory s);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.

Returns

NameTypeDescription
sSplitEstimated USDC allocations before existing staking fees.

harvestAndSplit

Harvest and allocate yield by economic capital, with a haircut on gross staking yield.

The vault credits userShare via its existing QEURO mint path. Failure rolls back the whole harvest.

Notes:

  • security: Principal is untouched; no fallback recipient silently captures hedger yield.

  • validation: Same capital validation as preview; nonzero hedger payout requires a recipient.

  • state-changes: Harvests adapter yield and transfers hedger/treasury USDC.

  • events: Adapter/token/oracle events; the vault emits distribution events.

  • errors: Propagates snapshot/adapter/token errors; ZeroAddress for missing recipient.

  • reentrancy: Caller holds its reentrancy guard.

  • access: Linked library.

  • oracle: Snapshot taken before harvesting and yield minting.

function harvestAndSplit(uint256 vaultId, mapping(uint256 => uint256) storage lastHarvest)
    external
    returns (uint256 userShare);

Parameters

NameTypeDescription
vaultIduint256Selected strategy.
lastHarvestmapping(uint256 => uint256)Keeper timestamps updated atomically with distribution.

Returns

NameTypeDescription
userShareuint256USDC allocation to credit through the existing QEURO mint path.

Events

UsdcWithdrawnFromExternalVault

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

StakingVaultConfigured

event StakingVaultConfigured(uint256 indexed vaultId, address indexed adapter, bool active);

ExternalVaultLossRealized

event ExternalVaultLossRealized(uint256 indexed vaultId, uint256 previousPrincipal, uint256 currentUnderlying);

RedemptionPriorityUpdated

event RedemptionPriorityUpdated(uint256[] vaultIds);

VaultYieldDistributed

event VaultYieldDistributed(
    uint256 indexed vaultId, uint256 realizedYield, uint256 hedgerShare, uint256 userShare, uint256 treasuryShare
);

VaultYieldBreakdown

event VaultYieldBreakdown(uint256 indexed vaultId, uint256 hedgerBase, uint256 stakingYieldHaircut);

Structs

DistributeParams

Configuration and capital registries supplied by the calling vault.

struct DistributeParams {
    address adapter;
    address stToken;
    address qeuro;
    address usdc;
    address treasury;
    address hedgerRecipient;
    uint256 principalUsdc;
    uint256 totalPrincipalUsdc;
    uint256 haircutBps;
    address factory;
    address hedgerPool;
    address oracle;
    uint256 vaultId;
}

Split

USDC amounts before the staking token's existing yield fee and execution costs.

struct Split {
    uint256 realizedYield;
    uint256 hedgerBase;
    uint256 haircut;
    uint256 hedgerShare;
    uint256 userShare;
    uint256 treasuryShare;
}

Capital

Harvest-time ownership snapshot, excluding the yield being distributed.

struct Capital {
    uint256 hedger;
    uint256 userBacking;
    uint256 staked;
    uint256 supply;
}