Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HousePool

Git Source

Inherits: ICfdVault, IHousePool, Ownable2Step, Pausable

Title: HousePool

Tranched house pool. Senior tranche gets fixed-rate yield with last-loss protection. Junior tranche absorbs first loss but captures surplus revenue.

Note: security-contact: contact@plether.com

Constants

USDC

IERC20 public immutable USDC

ENGINE

ICfdEngine public immutable ENGINE

TIMELOCK_DELAY

uint256 public constant TIMELOCK_DELAY = 48 hours

State Variables

orderRouter

address public orderRouter

seniorVault

address public seniorVault

juniorVault

address public juniorVault

seniorPrincipal

uint256 public seniorPrincipal

juniorPrincipal

uint256 public juniorPrincipal

unpaidSeniorYield

uint256 public unpaidSeniorYield

seniorHighWaterMark

uint256 public seniorHighWaterMark

accountedAssets

uint256 public accountedAssets

unassignedAssets

uint256 public unassignedAssets

pendingRecapitalizationUsdc

uint256 public pendingRecapitalizationUsdc

pendingTradingRevenueUsdc

uint256 public pendingTradingRevenueUsdc

lastReconcileTime

uint256 public lastReconcileTime

lastSeniorYieldCheckpointTime

uint256 public lastSeniorYieldCheckpointTime

seniorRateBps

uint256 public seniorRateBps

markStalenessLimit

uint256 public markStalenessLimit = 60

isTradingActive

bool public override(ICfdVault, IHousePool) isTradingActive

seniorSeedInitialized

bool public seniorSeedInitialized

juniorSeedInitialized

bool public juniorSeedInitialized

pendingSeniorRate

uint256 public pendingSeniorRate

seniorRateActivationTime

uint256 public seniorRateActivationTime

pendingMarkStalenessLimit

uint256 public pendingMarkStalenessLimit

markStalenessLimitActivationTime

uint256 public markStalenessLimitActivationTime

Functions

onlyVault

modifier onlyVault() ;

constructor

constructor(
    address _usdc,
    address _engine
) Ownable(msg.sender);

Parameters

NameTypeDescription
_usdcaddressUSDC token address used as collateral
_engineaddressCfdEngine that manages positions and PnL

setOrderRouter

Set the OrderRouter address (one-time, immutable after set)

function setOrderRouter(
    address _router
) external onlyOwner;

setSeniorVault

Set the senior tranche vault address (one-time, immutable after set)

function setSeniorVault(
    address _vault
) external onlyOwner;

setJuniorVault

Set the junior tranche vault address (one-time, immutable after set)

function setJuniorVault(
    address _vault
) external onlyOwner;

proposeSeniorRate

Propose a new senior yield rate, subject to 48h timelock

function proposeSeniorRate(
    uint256 _rateBps
) external onlyOwner;

finalizeSeniorRate

Finalize the proposed senior rate after timelock expires.

Syncs funding first. If the mark is stale, the new rate is applied without accruing stale-window senior yield.

function finalizeSeniorRate() external onlyOwner;

cancelSeniorRateProposal

Cancel the pending senior rate proposal

function cancelSeniorRateProposal() external onlyOwner;

proposeMarkStalenessLimit

Propose a new mark-price staleness limit, subject to 48h timelock

function proposeMarkStalenessLimit(
    uint256 _limit
) external onlyOwner;

finalizeMarkStalenessLimit

Finalize the proposed staleness limit after timelock expires

function finalizeMarkStalenessLimit() external onlyOwner;

cancelMarkStalenessLimitProposal

Cancel the pending staleness limit proposal

function cancelMarkStalenessLimitProposal() external onlyOwner;

pause

Pause deposits into both tranches

function pause() external onlyOwner;

unpause

Unpause deposits into both tranches

function unpause() external onlyOwner;

totalAssets

Canonical economic USDC backing recognized by the pool. Unsolicited positive transfers are ignored until explicitly accounted, while raw-balance shortfalls still reduce the effective backing.

function totalAssets() public view returns (uint256);

isSeedLifecycleComplete

function isSeedLifecycleComplete() public view returns (bool);

hasSeedLifecycleStarted

function hasSeedLifecycleStarted() public view override(ICfdVault, IHousePool) returns (bool);

canAcceptOrdinaryDeposits

function canAcceptOrdinaryDeposits() public view override(ICfdVault, IHousePool) returns (bool);

canAcceptTrancheDeposits

function canAcceptTrancheDeposits(
    bool isSenior
) public view override returns (bool);

canIncreaseRisk

function canIncreaseRisk() public view override(ICfdVault, IHousePool) returns (bool);

activateTrading

function activateTrading() external onlyOwner;

rawAssets

Raw USDC balance currently held by the pool, including unsolicited transfers.

function rawAssets() public view returns (uint256);

excessAssets

Raw USDC held above canonical accounted assets.

function excessAssets() public view returns (uint256);

accountExcess

Explicitly converts unsolicited USDC into accounted protocol assets. Syncs funding first so the added depth applies only going forward.

function accountExcess() external onlyOwner;

sweepExcess

Sweeps unsolicited USDC that has not been accounted into protocol economics.

function sweepExcess(
    address recipient,
    uint256 amount
) external onlyOwner;

payOut

Transfers USDC from the pool. Callable by CfdEngine (PnL/funding) or OrderRouter (keeper bounties).

function payOut(
    address recipient,
    uint256 amount
) external;

Parameters

NameTypeDescription
recipientaddressAddress to receive USDC
amountuint256USDC amount to transfer (6 decimals)

recordProtocolInflow

Accounts a legitimate protocol-owned inflow into canonical vault assets.

Only the engine or order router may use this path. Unlike accountExcess(), this does not require raw excess to exist: it is the explicit accounting hook for endogenous protocol gains and may also be used to restore canonical accounting after a raw-balance shortfall has already reduced effective assets through totalAssets() = min(raw, accounted).

function recordProtocolInflow(
    uint256 amount
) external;

recordRecapitalizationInflow

Accounts a governance recapitalization inflow and routes it toward senior restoration when possible.

This narrows the cases that fall into generic unassigned accounting when a seeded senior tranche exists.

function recordRecapitalizationInflow(
    uint256 amount
) external;

recordTradingRevenueInflow

Accounts LP-owned trading revenue and directly attaches it to seeded claimants when no live principal exists.

Used for realized trader losses / spread capture paths whose economic owner is LP equity rather than protocol fees.

function recordTradingRevenueInflow(
    uint256 amount
) external;

assignUnassignedAssets

Explicitly bootstraps quarantined LP assets into a tranche by minting matching shares.

Prevents later LPs from implicitly capturing value that arrived while no claimant shares existed.

function assignUnassignedAssets(
    bool toSenior,
    address receiver
) external onlyOwner;

initializeSeedPosition

Seeds a tranche with a permanent minimum share supply backed by real USDC.

Syncs funding first so the new seed depth only affects funding prospectively, then mints bootstrap shares to ensure a tranche never becomes ownerless in steady state.

function initializeSeedPosition(
    bool toSenior,
    uint256 amount,
    address receiver
) external onlyOwner;

depositSenior

Deposit USDC into the senior tranche. Reverts if senior is impaired (below high-water mark).

function depositSenior(
    uint256 amount
) external onlyVault whenNotPaused;

Parameters

NameTypeDescription
amountuint256USDC to deposit (6 decimals)

withdrawSenior

Withdraw USDC from the senior tranche. Scales high-water mark and unpaid yield proportionally.

function withdrawSenior(
    uint256 amount,
    address receiver
) external onlyVault;

Parameters

NameTypeDescription
amountuint256USDC to withdraw (6 decimals)
receiveraddressAddress to receive USDC

depositJunior

Deposit USDC into the junior tranche.

function depositJunior(
    uint256 amount
) external onlyVault whenNotPaused;

Parameters

NameTypeDescription
amountuint256USDC to deposit (6 decimals)

withdrawJunior

Withdraw USDC from the junior tranche. Limited to free USDC above senior’s claim.

function withdrawJunior(
    uint256 amount,
    address receiver
) external onlyVault;

Parameters

NameTypeDescription
amountuint256USDC to withdraw (6 decimals)
receiveraddressAddress to receive USDC

getFreeUSDC

Returns USDC not reserved for worst-case position payouts (max of bull/bear liability)

function getFreeUSDC() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Free USDC available for withdrawals (6 decimals)

getMaxSeniorWithdraw

Max USDC the senior tranche can withdraw (limited by free USDC)

function getMaxSeniorWithdraw() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Withdrawable senior USDC, capped at seniorPrincipal (6 decimals)

getMaxJuniorWithdraw

Max USDC the junior tranche can withdraw (subordinated behind senior)

function getMaxJuniorWithdraw() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Withdrawable junior USDC, capped at juniorPrincipal (6 decimals)

getPendingTrancheState

Returns tranche principals and withdrawal caps as if reconcile ran right now.

Read-only preview for ERC4626 consumers that need same-tx parity with reconcile-first vault flows.

function getPendingTrancheState()
    external
    view
    returns (
        uint256 seniorPrincipalUsdc,
        uint256 juniorPrincipalUsdc,
        uint256 maxSeniorWithdrawUsdc,
        uint256 maxJuniorWithdrawUsdc
    );

isWithdrawalLive

function isWithdrawalLive() external view returns (bool);

getVaultLiquidityView

Snapshot of pool liquidity, tranche principals, and oracle health for frontend consumption

function getVaultLiquidityView() external view returns (VaultLiquidityView memory viewData);

Returns

NameTypeDescription
viewDataVaultLiquidityViewStruct containing balances, reserves, and status flags

reconcile

Distributes revenue (senior yield first, junior gets surplus) or absorbs losses (junior first-loss, senior last-loss). Called before any deposit/withdrawal.

function reconcile() external onlyVault;

_requireFreshMark

function _requireFreshMark(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal view;

_reconcile

function _reconcile(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot
) internal;

_getWithdrawalSnapshot

function _getWithdrawalSnapshot()
    internal
    view
    returns (HousePoolAccountingLib.WithdrawalSnapshot memory snapshot);

_buildHousePoolContext

function _buildHousePoolContext(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal view returns (HousePoolContext memory ctx);

_syncAndBuildHousePoolContext

function _syncAndBuildHousePoolContext() internal returns (HousePoolContext memory ctx);

_buildCurrentHousePoolContext

function _buildCurrentHousePoolContext() internal view returns (HousePoolContext memory ctx);

_previewPendingAccountingState

function _previewPendingAccountingState(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal view returns (PendingAccountingState memory pendingState);

_markIsFreshForReconcile

function _markIsFreshForReconcile(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal view returns (bool);

_withdrawalsLive

function _withdrawalsLive(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal view returns (bool);

_normalizeUnassignedAssets

function _normalizeUnassignedAssets(
    uint256 distributableUsdc
) internal view returns (uint256 normalized);

_juniorShareSupply

function _juniorShareSupply() internal view returns (uint256);

_seniorShareSupply

function _seniorShareSupply() internal view returns (uint256);

_requireNoPendingBootstrap

function _requireNoPendingBootstrap() internal view;

_buildWithdrawalSnapshot

function _buildWithdrawalSnapshot(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    uint256 reservedUnassignedAssets,
    bool isProjected
) internal view returns (HousePoolAccountingLib.WithdrawalSnapshot memory snapshot);

_checkpointSeniorYieldBeforePrincipalMutation

function _checkpointSeniorYieldBeforePrincipalMutation(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal;

_applyPendingBucketsLive

function _applyPendingBucketsLive(
    ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal;

_applyPendingBucketsPreview

function _applyPendingBucketsPreview(
    PendingAccountingState memory state
) internal view;

_applyRecapitalizationIntent

function _applyRecapitalizationIntent(
    PendingAccountingState memory state,
    uint256 amount
) internal pure;

_routeSeededRevenue

function _routeSeededRevenue(
    PendingAccountingState memory state,
    uint256 amount
) internal pure;

_copyPendingAccountingState

function _copyPendingAccountingState(
    PendingAccountingState memory state
) internal pure returns (HousePoolPendingPreviewLib.PendingAccountingState memory copiedState);

_pendingBucketAssets

function _pendingBucketAssets() internal view returns (uint256);

_getHousePoolInputSnapshot

function _getHousePoolInputSnapshot() internal view returns (ICfdEngine.HousePoolInputSnapshot memory snapshot);

_getHousePoolStatusSnapshot

function _getHousePoolStatusSnapshot() internal view returns (ICfdEngine.HousePoolStatusSnapshot memory snapshot);

_getHousePoolSnapshots

function _getHousePoolSnapshots()
    internal
    view
    returns (
        ICfdEngine.HousePoolInputSnapshot memory accountingSnapshot,
        ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
    );

_requireWithdrawalsLive

function _requireWithdrawalsLive(
    ICfdEngine.HousePoolStatusSnapshot memory statusSnapshot
) internal pure;

_distributeRevenue

function _distributeRevenue(
    uint256 revenue
) internal;

_absorbLoss

function _absorbLoss(
    uint256 loss
) internal;

_getWaterfallState

function _getWaterfallState() internal view returns (HousePoolWaterfallAccountingLib.WaterfallState memory state);

_setWaterfallState

function _setWaterfallState(
    HousePoolWaterfallAccountingLib.WaterfallState memory state
) internal;

Events

Reconciled

event Reconciled(uint256 seniorPrincipal, uint256 juniorPrincipal, int256 delta);

SeniorRateUpdated

event SeniorRateUpdated(uint256 newRateBps);

MarkStalenessLimitUpdated

event MarkStalenessLimitUpdated(uint256 newLimit);

SeniorRateProposed

event SeniorRateProposed(uint256 newRateBps, uint256 activationTime);

SeniorRateFinalized

event SeniorRateFinalized();

MarkStalenessLimitProposed

event MarkStalenessLimitProposed(uint256 newLimit, uint256 activationTime);

MarkStalenessLimitFinalized

event MarkStalenessLimitFinalized();

ExcessAccounted

event ExcessAccounted(uint256 amountUsdc, uint256 accountedAssetsUsdc);

ExcessSwept

event ExcessSwept(address indexed recipient, uint256 amountUsdc);

ProtocolInflowAccounted

event ProtocolInflowAccounted(address indexed caller, uint256 amountUsdc, uint256 accountedAssetsUsdc);

RecapitalizationInflowAccounted

event RecapitalizationInflowAccounted(address indexed caller, uint256 amountUsdc, uint256 seniorRestorationUsdc);

TradingRevenueInflowAccounted

event TradingRevenueInflowAccounted(
    address indexed caller, uint256 amountUsdc, uint256 seniorAssignedUsdc, uint256 juniorAssignedUsdc
);

UnassignedAssetsAssigned

event UnassignedAssetsAssigned(
    bool indexed toSenior, address indexed receiver, uint256 amountUsdc, uint256 sharesMinted
);

SeedPositionInitialized

event SeedPositionInitialized(
    bool indexed toSenior, address indexed receiver, uint256 amountUsdc, uint256 sharesMinted
);

TradingActivated

event TradingActivated();

Errors

HousePool__NotAVault

error HousePool__NotAVault();

HousePool__RouterAlreadySet

error HousePool__RouterAlreadySet();

HousePool__SeniorVaultAlreadySet

error HousePool__SeniorVaultAlreadySet();

HousePool__JuniorVaultAlreadySet

error HousePool__JuniorVaultAlreadySet();

HousePool__Unauthorized

error HousePool__Unauthorized();

HousePool__ExceedsMaxSeniorWithdraw

error HousePool__ExceedsMaxSeniorWithdraw();

HousePool__ExceedsMaxJuniorWithdraw

error HousePool__ExceedsMaxJuniorWithdraw();

HousePool__MarkPriceStale

error HousePool__MarkPriceStale();

HousePool__TimelockNotReady

error HousePool__TimelockNotReady();

HousePool__NoProposal

error HousePool__NoProposal();

HousePool__SeniorImpaired

error HousePool__SeniorImpaired();

HousePool__DegradedMode

error HousePool__DegradedMode();

HousePool__ZeroAddress

error HousePool__ZeroAddress();

HousePool__ZeroStaleness

error HousePool__ZeroStaleness();

HousePool__InvalidSeniorRate

error HousePool__InvalidSeniorRate();

HousePool__NoExcessAssets

error HousePool__NoExcessAssets();

HousePool__ExcessAmountTooHigh

error HousePool__ExcessAmountTooHigh();

HousePool__PendingBootstrap

error HousePool__PendingBootstrap();

HousePool__NoUnassignedAssets

error HousePool__NoUnassignedAssets();

HousePool__BootstrapSharesZero

error HousePool__BootstrapSharesZero();

HousePool__SeedAlreadyInitialized

error HousePool__SeedAlreadyInitialized();

HousePool__TradingActivationNotReady

error HousePool__TradingActivationNotReady();

Structs

VaultLiquidityView

struct VaultLiquidityView {
    uint256 totalAssetsUsdc;
    uint256 freeUsdc;
    uint256 withdrawalReservedUsdc;
    uint256 seniorPrincipalUsdc;
    uint256 juniorPrincipalUsdc;
    uint256 unpaidSeniorYieldUsdc;
    uint256 seniorHighWaterMarkUsdc;
    bool markFresh;
    bool oracleFrozen;
    bool degradedMode;
}

PendingAccountingState

struct PendingAccountingState {
    HousePoolWaterfallAccountingLib.WaterfallState waterfall;
    uint256 unassignedAssets;
    uint256 seniorSupply;
    uint256 juniorSupply;
}

HousePoolContext

struct HousePoolContext {
    ICfdEngine.HousePoolInputSnapshot accountingSnapshot;
    ICfdEngine.HousePoolStatusSnapshot statusSnapshot;
    PendingAccountingState pendingState;
}