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

MarginClearinghouse

Git Source

Inherits: Ownable2Step

Title: MarginClearinghouse

USDC-only cross-margin account manager for Plether.

Holds settlement balances and locked margin for CFD accounts.

Note: security-contact: contact@plether.com

Constants

settlementAsset

address public immutable settlementAsset

State Variables

settlementBalances

mapping(bytes32 => uint256) internal settlementBalances

positionMarginUsdc

mapping(bytes32 => uint256) internal positionMarginUsdc

committedOrderMarginUsdc

mapping(bytes32 => uint256) internal committedOrderMarginUsdc

reservedSettlementUsdc

mapping(bytes32 => uint256) internal reservedSettlementUsdc

orderReservations

mapping(uint64 => IMarginClearinghouse.OrderReservation) internal orderReservations

reservationIdsByAccount

mapping(bytes32 => uint64[]) internal reservationIdsByAccount

reservationHeadIndexByAccount

mapping(bytes32 => uint256) internal reservationHeadIndexByAccount

activeCommittedOrderReservationUsdc

mapping(bytes32 => uint256) internal activeCommittedOrderReservationUsdc

activeReservedSettlementReservationUsdc

mapping(bytes32 => uint256) internal activeReservedSettlementReservationUsdc

activeReservationCount

mapping(bytes32 => uint256) internal activeReservationCount

engine

address public engine

Functions

onlyOperator

modifier onlyOperator() ;

constructor

constructor(
    address _settlementAsset
) Ownable(msg.sender);

Parameters

NameTypeDescription
_settlementAssetaddressUSDC address used for PnL settlement and margin backing

setEngine

Sets the CfdEngine address (one-time, reverts if already set).

function setEngine(
    address _engine
) external onlyOwner;

deposit

Deposits settlement USDC into the specified margin account.

function deposit(
    bytes32 accountId,
    uint256 amount
) external;

Parameters

NameTypeDescription
accountIdbytes32Deterministic account ID derived from msg.sender address
amountuint256Token amount to transfer in

withdraw

Withdraws settlement USDC from a margin account.

function withdraw(
    bytes32 accountId,
    uint256 amount
) external;

Parameters

NameTypeDescription
accountIdbytes32Deterministic account ID derived from msg.sender address
amountuint256USDC amount to withdraw

getAccountEquityUsdc

Returns the total USD buying power of the account (6 decimals).

function getAccountEquityUsdc(
    bytes32 accountId
) public view returns (uint256 totalEquityUsdc);

Parameters

NameTypeDescription
accountIdbytes32Account to value

Returns

NameTypeDescription
totalEquityUsdcuint256Settlement balance in USDC (6 decimals)

getFreeBuyingPowerUsdc

Returns strictly unencumbered purchasing power

function getFreeBuyingPowerUsdc(
    bytes32 accountId
) public view returns (uint256);

Parameters

NameTypeDescription
accountIdbytes32Account to query

Returns

NameTypeDescription
<none>uint256Equity minus locked margin, floored at zero (6 decimals)

getAccountUsdcBuckets

Returns the explicit USDC bucket split after subtracting the clearinghouse’s typed locked-margin buckets.

function getAccountUsdcBuckets(
    bytes32 accountId
) public view returns (IMarginClearinghouse.AccountUsdcBuckets memory buckets);

getFreeSettlementBalanceUsdc

function getFreeSettlementBalanceUsdc(
    bytes32 accountId
) public view returns (uint256);

getTerminalReachableUsdc

Returns settlement balance reachable by a terminal settlement path.

function getTerminalReachableUsdc(
    bytes32 accountId
) public view returns (uint256);

getSettlementReachableUsdc

Returns settlement balance reachable after protecting only an explicitly remaining margin bucket.

This is the canonical helper for terminal settlement paths: full closes and liquidations should pass zero protected margin, while partial closes should protect only the residual position margin that remains open after settlement.

function getSettlementReachableUsdc(
    bytes32 accountId,
    uint256 protectedLockedMarginUsdc
) public view returns (uint256);

lockPositionMargin

Locks margin to back a new CFD trade. Requires sufficient USDC to back settlement (non-USDC equity alone is insufficient).

function lockPositionMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to lock margin on
amountUsdcuint256USDC amount to lock (6 decimals)

unlockPositionMargin

Unlocks active position margin when a CFD trade closes

function unlockPositionMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to unlock margin on
amountUsdcuint256USDC amount to unlock (6 decimals), clamped to current locked amount

lockCommittedOrderMargin

Locks margin to back a pending order commitment.

function lockCommittedOrderMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to lock margin on
amountUsdcuint256USDC amount to lock (6 decimals)

reserveCommittedOrderMargin

function reserveCommittedOrderMargin(
    bytes32 accountId,
    uint64 orderId,
    uint256 amountUsdc
) external onlyOperator;

unlockCommittedOrderMargin

Unlocks committed order margin when an order is cancelled or filled.

function unlockCommittedOrderMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to unlock margin on
amountUsdcuint256USDC amount to unlock (6 decimals)

releaseOrderReservation

function releaseOrderReservation(
    uint64 orderId
) external onlyOperator returns (uint256 releasedUsdc);

releaseOrderReservationIfActive

function releaseOrderReservationIfActive(
    uint64 orderId
) external onlyOperator returns (uint256 releasedUsdc);

consumeOrderReservation

function consumeOrderReservation(
    uint64 orderId,
    uint256 amountUsdc
) external onlyOperator returns (uint256 consumedUsdc);

consumeAccountOrderReservations

function consumeAccountOrderReservations(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator returns (uint256 consumedUsdc);

consumeOrderReservationsById

function consumeOrderReservationsById(
    uint64[] calldata orderIds,
    uint256 amountUsdc
) external onlyOperator returns (uint256 consumedUsdc);

_consumeOrderReservationsById

function _consumeOrderReservationsById(
    uint64[] memory orderIds,
    uint256 amountUsdc
) internal returns (uint256 consumedUsdc);

_consumeAccountOrderReservations

function _consumeAccountOrderReservations(
    bytes32 accountId,
    uint256 amountUsdc,
    bool consumeBuckets
) internal returns (uint256 consumedUsdc);

_releaseReservation

function _releaseReservation(
    IMarginClearinghouse.OrderReservation storage reservation,
    bool consumeBuckets
) internal returns (uint256 releasedUsdc);

_consumeReservation

function _consumeReservation(
    IMarginClearinghouse.OrderReservation storage reservation,
    uint256 amountUsdc,
    bool consumeBuckets,
    IMarginClearinghouse.ReservationStatus terminalStatus
) internal;

_decreaseActiveReservation

function _decreaseActiveReservation(
    bytes32 accountId,
    IMarginClearinghouse.ReservationBucket bucket,
    uint256 amountUsdc
) internal;

lockReservedSettlement

function lockReservedSettlement(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

unlockReservedSettlement

function unlockReservedSettlement(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

settleUsdc

Adjusts USDC balance to settle funding, PnL, and VPI rebates. Positive amounts credit the account; negative amounts debit it.

function settleUsdc(
    bytes32 accountId,
    int256 amount
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to settle
amountint256Signed USDC delta: positive credits, negative debits (6 decimals)

creditSettlementAndLockMargin

Credits settlement USDC and locks the same amount as active margin.

function creditSettlementAndLockMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external onlyOperator;

applyOpenCost

Applies an open/increase trade cost by debiting or crediting settlement and updating locked margin.

function applyOpenCost(
    bytes32 accountId,
    uint256 marginDeltaUsdc,
    int256 tradeCostUsdc,
    address recipient
) external onlyOperator returns (int256 netMarginChangeUsdc);

consumeFundingLoss

Consumes a funding loss from free settlement first, then from the active position margin bucket.

Unrelated locked margin remains protected.

function consumeFundingLoss(
    bytes32 accountId,
    uint256,
    uint256 lossUsdc,
    address recipient
)
    external
    onlyOperator
    returns (uint256 marginConsumedUsdc, uint256 freeSettlementConsumedUsdc, uint256 uncoveredUsdc);

consumeCloseLoss

Consumes close-path losses from settlement buckets while preserving any explicitly protected remaining position margin.

function consumeCloseLoss(
    bytes32 accountId,
    uint64[] calldata reservationOrderIds,
    uint256 lossUsdc,
    uint256 protectedLockedMarginUsdc,
    bool includeOtherLockedMargin,
    address recipient
) external onlyOperator returns (uint256 seizedUsdc, uint256 shortfallUsdc);

applyLiquidationSettlementPlan

Applies a pre-planned liquidation settlement mutation.

Releases the active position margin bucket and covered committed margin exactly as planned.

function applyLiquidationSettlementPlan(
    bytes32 accountId,
    uint64[] calldata reservationOrderIds,
    IMarginClearinghouse.LiquidationSettlementPlan calldata plan,
    address recipient
) external onlyOperator returns (uint256 seizedUsdc);

_buildAccountUsdcBuckets

function _buildAccountUsdcBuckets(
    bytes32 accountId
) internal view returns (IMarginClearinghouse.AccountUsdcBuckets memory buckets);

_planFundingLossConsumption

function _planFundingLossConsumption(
    bytes32 accountId,
    uint256 lossUsdc
) internal view returns (MarginClearinghouseAccountingLib.SettlementConsumption memory consumption);

_creditSettlementUsdc

function _creditSettlementUsdc(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_debitSettlementUsdc

function _debitSettlementUsdc(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_lockMargin

function _lockMargin(
    bytes32 accountId,
    IMarginClearinghouse.MarginBucket bucket,
    uint256 amountUsdc
) internal;

_unlockMargin

function _unlockMargin(
    bytes32 accountId,
    IMarginClearinghouse.MarginBucket bucket,
    uint256 amountUsdc
) internal;

_consumeOtherLockedMargin

Consumes non-position locked margin by priority: committed-order margin first, then reserved settlement. Queued order margin is released before reserved settlement because failed/cancelled order intents are softer obligations than explicitly reserved settlement buckets.

function _consumeOtherLockedMargin(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_consumeOtherLockedMarginViaReservations

function _consumeOtherLockedMarginViaReservations(
    bytes32 accountId,
    uint64[] calldata reservationOrderIds,
    uint256 amountUsdc
) internal;

_consumeReservationBucket

function _consumeReservationBucket(
    bytes32 accountId,
    IMarginClearinghouse.ReservationBucket bucket,
    uint256 amountUsdc
) internal;

_activeReservation

function _activeReservation(
    uint64 orderId
) internal view returns (IMarginClearinghouse.OrderReservation storage reservation);

_closeReservation

function _closeReservation(
    IMarginClearinghouse.OrderReservation storage reservation,
    IMarginClearinghouse.ReservationStatus terminalStatus
) internal;

_advanceReservationHead

function _advanceReservationHead(
    bytes32 accountId
) internal;

_consumeLockedMargin

function _consumeLockedMargin(
    bytes32 accountId,
    IMarginClearinghouse.MarginBucket bucket,
    uint256 amountUsdc
) internal;

_bucketStorage

function _bucketStorage(
    IMarginClearinghouse.MarginBucket bucket,
    bytes32 accountId
) internal view returns (uint256 bucketValue);

_setBucketStorage

function _setBucketStorage(
    IMarginClearinghouse.MarginBucket bucket,
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_totalLockedMarginUsdc

function _totalLockedMarginUsdc(
    bytes32 accountId
) internal view returns (uint256);

seizeUsdc

Transfers settlement USDC from an account to the calling operator.

The recipient must equal msg.sender, so operators can only pull seized funds into their own contract/account and must forward them explicitly afterward.

function seizeUsdc(
    bytes32 accountId,
    uint256 amount,
    address recipient
) external onlyOperator;

Parameters

NameTypeDescription
accountIdbytes32Account to seize from
amountuint256USDC amount to seize
recipientaddressRecipient of seized tokens (must equal msg.sender)

seizePositionMarginUsdc

function seizePositionMarginUsdc(
    bytes32 accountId,
    uint256 amount,
    address recipient
) external onlyOperator;

balanceUsdc

function balanceUsdc(
    bytes32 accountId
) external view returns (uint256);

lockedMarginUsdc

function lockedMarginUsdc(
    bytes32 accountId
) external view returns (uint256);

getLockedMarginBuckets

function getLockedMarginBuckets(
    bytes32 accountId
) external view returns (IMarginClearinghouse.LockedMarginBuckets memory buckets);

getOrderReservation

function getOrderReservation(
    uint64 orderId
) external view returns (IMarginClearinghouse.OrderReservation memory reservation);

getAccountReservationSummary

function getAccountReservationSummary(
    bytes32 accountId
) external view returns (IMarginClearinghouse.AccountReservationSummary memory summary);

reservationHeadIndex

function reservationHeadIndex(
    bytes32 accountId
) external view returns (uint256);

_toUint96

function _toUint96(
    uint256 value
) internal pure returns (uint96);

Events

Deposit

event Deposit(bytes32 indexed accountId, address indexed asset, uint256 amount);

Withdraw

event Withdraw(bytes32 indexed accountId, address indexed asset, uint256 amount);

MarginLocked

event MarginLocked(bytes32 indexed accountId, IMarginClearinghouse.MarginBucket indexed bucket, uint256 amountUsdc);

MarginUnlocked

event MarginUnlocked(
    bytes32 indexed accountId, IMarginClearinghouse.MarginBucket indexed bucket, uint256 amountUsdc
);

ReservationCreated

event ReservationCreated(
    uint64 indexed orderId,
    bytes32 indexed accountId,
    IMarginClearinghouse.ReservationBucket indexed bucket,
    uint256 amountUsdc
);

ReservationConsumed

event ReservationConsumed(
    uint64 indexed orderId, bytes32 indexed accountId, uint256 amountUsdc, uint256 remainingAmountUsdc
);

ReservationReleased

event ReservationReleased(uint64 indexed orderId, bytes32 indexed accountId, uint256 amountUsdc);

AssetSeized

event AssetSeized(bytes32 indexed accountId, address indexed asset, uint256 amount, address recipient);

Errors

MarginClearinghouse__NotOperator

error MarginClearinghouse__NotOperator();

MarginClearinghouse__NotAccountOwner

error MarginClearinghouse__NotAccountOwner();

MarginClearinghouse__ZeroAmount

error MarginClearinghouse__ZeroAmount();

MarginClearinghouse__InsufficientBalance

error MarginClearinghouse__InsufficientBalance();

MarginClearinghouse__InsufficientFreeEquity

error MarginClearinghouse__InsufficientFreeEquity();

MarginClearinghouse__InsufficientUsdcForSettlement

error MarginClearinghouse__InsufficientUsdcForSettlement();

MarginClearinghouse__InsufficientAssetToSeize

error MarginClearinghouse__InsufficientAssetToSeize();

MarginClearinghouse__InvalidSeizeRecipient

error MarginClearinghouse__InvalidSeizeRecipient();

MarginClearinghouse__InvalidMarginBucket

error MarginClearinghouse__InvalidMarginBucket();

MarginClearinghouse__ReservationAlreadyExists

error MarginClearinghouse__ReservationAlreadyExists();

MarginClearinghouse__ReservationNotActive

error MarginClearinghouse__ReservationNotActive();

MarginClearinghouse__IncompleteReservationCoverage

error MarginClearinghouse__IncompleteReservationCoverage();

MarginClearinghouse__EngineAlreadySet

error MarginClearinghouse__EngineAlreadySet();

MarginClearinghouse__ZeroAddress

error MarginClearinghouse__ZeroAddress();

MarginClearinghouse__InsufficientBucketMargin

error MarginClearinghouse__InsufficientBucketMargin();

MarginClearinghouse__AmountOverflow

error MarginClearinghouse__AmountOverflow();