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

Plether Protocol

CI Coverage License: AGPL v3 Solidity

Plether is a DeFi protocol for synthetic dollar-denominated tokens with inverse and direct exposure to the US Dollar Index (USDX). Users deposit USDC to mint paired tokens that track USD strength, enabling speculation and hedging on dollar movements.

How It Works

The protocol creates two synthetic tokens from USDC collateral:

  • plDXY-BEAR - Appreciates when USD weakens (USDX falls)
  • plDXY-BULL - Appreciates when USD strengthens (USDX rises)

These tokens are always minted and burned in pairs, maintaining a zero-sum relationship. When you deposit 100 USDC, you receive equal amounts of both tokens. The combined value of a BEAR + BULL pair always equals the original USDC deposit.

How It Works

Architecture

Core Contracts

ContractDescription
SyntheticSplitterCentral protocol contract. Accepts USDC, mints/burns token pairs. Permissionless deployToAdapter() pushes idle USDC to yield. EIP-2612 permit support on mint.
SyntheticTokenERC20 + ERC20FlashMint implementation for plDXY-BEAR and plDXY-BULL

Staking Layer

ContractDescription
StakedTokenERC-4626 vault wrapper (splDXY-BEAR, splDXY-BULL) with streaming rewards to prevent reward sniping
RewardDistributorDistributes USDC yield to StakedToken vaults, favoring the underperforming token

Oracle Layer

ContractDescription
BasketOracleComputes plDXY as weighted basket of 6 price feeds, with bound validation against Curve EMA price
PythAdapterAdapts Pyth Network feeds to Chainlink’s AggregatorV3Interface (used for SEK/USD)
MorphoOracleAdapts BasketOracle to Morpho Blue’s oracle scale (24 decimals for USDC/plDXY)
StakedOracleWraps underlying oracle to price ERC-4626 staked token shares

BasketOracle Design

The BasketOracle computes a USDX-like index using normalized arithmetic weighting rather than the geometric weighting of the official ICE USDX index:

Price = Σ(Weight_i × Price_i / BasePrice_i)

Each currency’s contribution is normalized by its base price, ensuring the intended USDX weights are preserved regardless of absolute FX rate scales. Without normalization, low-priced currencies like JPY (~$0.007) would be nearly ignored compared to EUR (~$1.08), causing severe weight distortion.

This design enables gas-efficient on-chain computation and eliminates rebalancing requirements, which guarantees protocol solvency.

Inverse Relationship: Because the oracle measures the USD value of a foreign currency basket, it moves inversely to the real USDX index. When the dollar strengthens, USDX rises but our basket value falls (foreign currencies are worth less in USD terms). This is why plDXY-BEAR appreciates when the basket value rises (dollar weakens).

Fixed Base Prices and Weights (immutable, set at deployment based on January 1, 2026 prices):

CurrencyWeightBase Price (USD)
EUR57.6%1.1750
JPY13.6%0.00638
GBP11.9%1.3448
CAD9.1%0.7288
SEK4.2%0.1086
CHF3.6%1.2610

Both weights and base prices are permanently fixed and cannot be changed after deployment.

Routing Layer

ContractDescription
ZapRouterSingle-sided plDXY-BULL minting and burning using flash mints. Permit support.
LeverageRouterLeveraged plDXY-BEAR positions via Morpho Blue flash loans. Open/close/add/remove collateral. Permit support.
BullLeverageRouterLeveraged plDXY-BULL positions via Morpho + plDXY-BEAR flash mints. Open/close/add/remove collateral. Permit support.

Yield Adapters (ERC-4626)

ContractDescription
VaultAdapterERC-4626 wrapper for Morpho Vault vault yield. Owner can claimRewards() from external distributors (Merkl, URD).

InvarCoin (INVAR)

ContractDescription
InvarCoinGlobal purchasing power vault backed 50/50 by USDC + plDXY-BEAR via Curve LP

InvarCoin is a passive savings token that maintains exposure to a basket of global currencies. Users deposit USDC, which the vault pairs with plDXY-BEAR through Curve to create a balanced position that hedges against USD weakness.

Deposit flow: USDC in → mint INVAR shares (priced against optimistic NAV to prevent dilution).

Deposit Flow

Withdraw flow: Burn INVAR → receive USDC from local buffer + JIT Curve LP unwinding. An EMA-based slippage floor prevents MEV sandwich amplification on the Curve leg.

Withdraw Flow

LP deposit: Advanced path for depositing USDC + BEAR directly into Curve LP.

LP Deposit Flow

LP withdraw: Balanced exit returning pro-rata USDC + BEAR. lpWithdraw intentionally works when paused, serving as the emergency exit.

LP Withdraw Flow

Yield: Curve LP trading fees accrue as virtual price growth. Keepers call harvest() to mint INVAR proportional to the fee yield and donate it to sINVAR (StakedToken) stakers via a 1-hour streaming window. Only fee yield is captured — price appreciation of the underlying assets is excluded via VP-based cost tracking.

Operational setup sequence:

  • Deploy InvarCoin and StakedToken, then call proposeStakedInvarCoin(sINVAR)
  • Wait STAKED_INVAR_TIMELOCK (7 days), then call finalizeStakedInvarCoin() before relying on harvest/donation flows
  • Propose the reward sink with proposeGaugeRewardsReceiver(receiver)
  • Wait GAUGE_REWARDS_TIMELOCK (7 days), then call finalizeGaugeRewardsReceiver()
  • Mark CRV and any other gauge incentives with protectRewardToken(token) so they cannot be swept with rescueToken()
  • After claiming rewards, route protected balances only through sweepGaugeRewards(token)

Keeper operations:

  • deployToCurve() — pushes excess USDC buffer (>2% target) into single-sided Curve LP
  • replenishBuffer() — burns Curve LP to restore the 2% USDC buffer
  • harvest() — captures LP fee yield and streams to sINVAR stakers

Safety:

  • Dual LP pricing: pessimistic (min of EMA, oracle) for withdrawals, optimistic (max) for deposits
  • Spot-vs-EMA deviation guard (0.5%) blocks deposits/deployments during pool manipulation
  • Virtual shares (1e18/1e6) prevent first-depositor inflation attacks
  • totalAssets() is a best-effort NAV view for UX/monitoring; use totalAssetsValidated() for strict oracle-validated accounting reads
  • _harvestSafe() gracefully skips when Curve VP reads fail; if yield is pending, strict oracle validation is still enforced
  • setEmergencyMode() pauses deposits and single-sided withdrawals without discarding LP accounting; emergencyWithdrawFromCurve() only zeroes LP tracking after assets are actually recovered
  • stakedInvarCoin and gaugeRewardsReceiver both use 7-day timelocked propose/finalize flows
  • Protected reward tokens cannot be rescued arbitrarily and must be swept to the configured reward receiver
  • L2 sequencer uptime validation is enforced on state-changing oracle-critical flows (deposit/lpDeposit/harvest/deploy/replenish)

Ecosystem Integrations

Token Flow

Token Flow

  • Chainlink - Price feeds for EUR/USD, JPY/USD, GBP/USD, CAD/USD, CHF/USD
  • Pyth Network - Price feed for SEK/USD (via PythAdapter)
  • Curve Finance - AMM pools for USDC/plDXY-BEAR swaps
  • Morpho Vault - Yield generation on idle USDC reserves via VaultAdapter

Bear Leverage

Bear Leverage

Flash loan USDC from Morpho → swap to plDXY-BEAR on Curve → stake → deposit splDXY-BEAR as Morpho collateral.

Bull Leverage

Bull Leverage

Flash loan USDC from Morpho → mint BEAR+BULL pairs → sell BEAR on Curve → stake BULL → deposit splDXY-BULL as Morpho collateral.

Both routers use fee-free Morpho flash loans and a fixed debt model: debt = principal × (leverage - 1).

Staking & Rewards

Staking & Rewards

  • StakedToken - ERC-4626 vaults (splDXY-BEAR, splDXY-BULL) that receive streaming USDC rewards
  • RewardDistributor - Permissionless distributeRewards() allocates yield from SyntheticSplitter, favoring the underperforming token’s stakers to incentivize price convergence

Protocol Mechanics

Liquidity Management

The SyntheticSplitter maintains a 10% local buffer of USDC for redemptions. Anyone can call deployToAdapter() to push excess USDC to yield adapters, targeting 90% deployment. This generates yield while ensuring liquidity for normal operations.

If adapter liquidity is constrained (e.g., high Morpho utilization), the owner can pause the protocol and use withdrawFromAdapter() for gradual extraction as liquidity becomes available.

Leverage

Users can open leveraged positions through the routers:

  1. LeverageRouter (Bear): Morpho flash loan USDC → Swap to plDXY-BEAR → Stake → Deposit to Morpho as collateral → Borrow USDC to repay flash loan
  2. BullLeverageRouter (Bull): Morpho flash loan USDC → Mint pairs → Sell plDXY-BEAR → Stake plDXY-BULL → Deposit to Morpho → Borrow to repay

Both routers use a fixed debt model: debt = principal × (leverage - 1). For 2x leverage with $100 principal, Morpho debt is always $100.

Morpho Blue provides fee-free flash loans, making leveraged positions more capital-efficient.

After opening, users can adjust positions with addCollateral() and removeCollateral() without closing.

Both routers include MEV protection via user-defined slippage caps (max 1%). All USDC entry points support EIP-2612 permits for gasless approvals.

Reward Distribution

The RewardDistributor receives yield from SyntheticSplitter and allocates it to StakedToken vaults based on the price discrepancy between the oracle and Curve EMA:

  • ≥2% discrepancy: 100% to underperforming token stakers
  • <2% discrepancy: Quadratic interpolation from 50/50 toward 100/0
  • 0% discrepancy: 50/50 split

This mechanism incentivizes arbitrageurs to correct price deviations by rewarding stakers of the underpriced token. A 0.1% caller reward incentivizes permissionless distribution.

Lifecycle States

The protocol operates in three states:

  1. ACTIVE - Normal operations (mint, burn, swap). If Chainlink and Curve EMA prices diverge >2%, BasketOracle reverts, blocking minting, leverage, and reward distribution until prices converge. Burns and swaps remain available—the 10% liquid buffer ensures users can always exit.
  2. PAUSED - Emergency pause (minting and reward distribution blocked, burning allowed so users can exit, gradual adapter withdrawal enabled)
  3. SETTLED - End-of-life when plDXY hits CAP price (only redemptions allowed)

Development

Prerequisites

Build

forge build

Test

forge test              # Run all tests
forge test -vvv         # Verbose output
forge coverage          # Generate coverage report

Fork Tests

Fork tests run against mainnet state using real Chainlink oracles, Curve pools, and Morpho Blue. They require an RPC URL:

# Set RPC URL (or add to .env file)
export MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY

# Run all fork tests
forge test --match-path "test/fork/*.sol" --fork-url $MAINNET_RPC_URL -vvv

# Or source from .env
source .env && forge test --match-path "test/fork/*.sol" --fork-url $MAINNET_RPC_URL -vvv

Fork test files:

FileDescription
BaseForkTest.solShared base contract, constants, and test helpers
ZapRouterFork.t.solZapRouter integration with real Curve swaps
FullCycleFork.t.solComplete mint → yield → burn lifecycle
LeverageRouterFork.t.solBear and Bull leverage via real Morpho
SlippageProtectionFork.t.solMEV protection and slippage scenarios
LiquidationFork.t.solInterest accrual and liquidation mechanics
BasketOracleFork.t.solFull 6-feed plDXY basket oracle validation
RewardDistributorFork.t.solReward distribution with real oracle prices
YieldIntegrationFork.t.solE2E yield pipeline: Morpho vault → harvest → distribute → staker share price
PermitFork.t.solEIP-2612 permit-based deposits
SlippageReport.t.solSlippage analysis across trade sizes

Run a specific fork test file:

source .env && forge test --match-path test/fork/LeverageRouterFork.t.sol --fork-url $MAINNET_RPC_URL -vvv

Testnet Deployment

Sepolia

Deploy to Sepolia testnet with a custom Morpho Blue instance (the public Morpho on Sepolia has no enabled IRMs/LLTVs):

# Required environment variables in .env:
# TEST_PRIVATE_KEY=0x...  (your deployer private key)
# SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY

# Deploy (43 transactions - may take a few minutes)
source .env && forge script script/DeployToSepolia.s.sol --tc DeployToSepolia \
  --rpc-url $SEPOLIA_RPC_URL \
  --broadcast

# Verify contracts on Etherscan (optional)
# ETHERSCAN_API_KEY=... in .env
source .env && forge verify-contract <ADDRESS> <CONTRACT> \
  --chain sepolia --etherscan-api-key $ETHERSCAN_API_KEY

The Sepolia deployment script:

  • Deploys its own Morpho Blue instance with a ZeroRateIrm (0% interest for testnet)
  • Creates all protocol contracts, oracles, and routers
  • Seeds Curve pool and Morpho markets with liquidity
  • Mints 100k MockUSDC to the deployer

Anvil (Local)

For frontend development and testing without spending real ETH:

# 1. Start local Anvil node forking Ethereum mainnet
anvil --fork-url $MAINNET_RPC_URL --chain-id 31337

# 2. Deploy all contracts with real Chainlink/Pyth oracles (mints 100k USDC to deployer)
TEST_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d \
forge script script/DeployToAnvilFork.s.sol --tc DeployToAnvilFork \
  --rpc-url http://127.0.0.1:8545 \
  --broadcast

# 3. (Optional) Simulate yield accrual (1% of adapter assets)
cast send <MOCK_YIELD_ADAPTER> "generateYield()" \
  --rpc-url http://127.0.0.1:8545 \
  --private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

# 4. (Optional) Seed Morpho markets for leverage testing
#    Morpho seeding is built into DeployToTest.s.sol for testnet deploys.
#    For Anvil fork, create markets manually using cast commands.

The Anvil fork deployment uses real mainnet oracles (Chainlink for EUR/JPY/GBP/CAD/CHF, Pyth for SEK) with prices frozen at the fork block. MockUSDC and MockYieldAdapter are still used for flexible testing.

Anvil Test Accounts (pre-funded with 10,000 ETH each):

AccountAddressPrivate Key
#00xf39Fd6e51aad88F6F4ce6aB8827279cffFb922660xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
#10x70997970C51812dc3A010C7d01b50e0d17dc79C80x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

MetaMask Setup:

  1. Import a test private key (Settings → Import Account)
  2. Add network: RPC http://127.0.0.1:8545, Chain ID 31337

Format

forge fmt               # Format code
forge fmt --check       # Check formatting

Documentation

View Reference Documentation

Generate HTML documentation locally from NatSpec comments:

forge doc               # Generate docs to ./docs
forge doc --serve       # Serve docs locally at http://localhost:3000
forge doc --build       # Build static site to ./docs/book

Security

  • All contracts use OpenZeppelin’s battle-tested implementations
  • Reentrancy protection on state-changing functions
  • 7-day timelock for critical governance changes
  • Oracle staleness checks (8–24 hour timeouts depending on context)
  • Oracle bound validation against Curve EMA to prevent price manipulation
  • Flash loan callback validation (initiator + lender checks)
  • Yield adapter uses Morpho Vault vault accounting for yield generation

For detailed security assumptions, trust model, and emergency procedures, see SECURITY.md.

License

AGPL-3.0

Disclaimer

This software is provided “as is” without warranty of any kind. Use at your own risk. This protocol has not been audited. Do not use in production without a professional security audit.

Contents

FlashLoanBase

Git Source

Inherits: IERC3156FlashBorrower, IMorphoFlashLoanCallback

Title: FlashLoanBase

Abstract base for flash loan borrowers with validation logic.

Supports both Morpho flash loans and ERC-3156 flash mints.

Constants

CALLBACK_SUCCESS

ERC-3156 callback success return value.

bytes32 internal constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");

Functions

_validateFlashLoan

Validates ERC-3156 flash loan callback parameters.

function _validateFlashLoan(
    address lender,
    address expectedLender,
    address initiator
) internal view;

Parameters

NameTypeDescription
lenderaddressActual msg.sender.
expectedLenderaddressExpected flash lender address.
initiatoraddressInitiator passed to callback (must be this contract).

_validateLender

Validates that msg.sender is the expected lender.

function _validateLender(
    address lender,
    address expectedLender
) internal pure;

Parameters

NameTypeDescription
lenderaddressActual msg.sender.
expectedLenderaddressExpected flash lender address.

Errors

FlashLoan__InvalidLender

Thrown when flash loan callback called by wrong lender.

error FlashLoan__InvalidLender();

FlashLoan__InvalidInitiator

Thrown when flash loan initiator is not this contract.

error FlashLoan__InvalidInitiator();

FlashLoan__InvalidOperation

Thrown when callback receives unknown operation type.

error FlashLoan__InvalidOperation();

LeverageRouterBase

Git Source

Inherits: FlashLoanBase, Ownable2Step, Pausable, ReentrancyGuard

Title: LeverageRouterBase

Abstract base for leverage routers with shared validation and admin logic.

Common infrastructure for LeverageRouter (plDXY-BEAR) and BullLeverageRouter (plDXY-BULL).

Note: security-contact: contact@plether.com

Constants

MAX_SLIPPAGE_BPS

Maximum slippage in basis points (1% = 100 bps).

uint256 public constant MAX_SLIPPAGE_BPS = 100;

EXCHANGE_RATE_BUFFER_BPS

Buffer for exchange rate drift protection (1% = 100 bps).

uint256 public constant EXCHANGE_RATE_BUFFER_BPS = 100;

USDC_INDEX

USDC index in Curve USDC/plDXY-BEAR pool.

uint256 public constant USDC_INDEX = 0;

PLDXY_BEAR_INDEX

plDXY-BEAR index in Curve USDC/plDXY-BEAR pool.

uint256 public constant PLDXY_BEAR_INDEX = 1;

OP_OPEN

Operation type: open leverage position.

uint8 internal constant OP_OPEN = 1;

OP_CLOSE

Operation type: close leverage position.

uint8 internal constant OP_CLOSE = 2;

MORPHO

Morpho Blue lending protocol.

IMorpho public immutable MORPHO;

CURVE_POOL

Curve pool for USDC/plDXY-BEAR swaps.

ICurvePool public immutable CURVE_POOL;

USDC

USDC stablecoin.

IERC20 public immutable USDC;

PLDXY_BEAR

plDXY-BEAR token.

IERC20 public immutable PLDXY_BEAR;

State Variables

marketParams

Morpho market configuration.

MarketParams public marketParams;

Functions

constructor

Initializes base router with core dependencies.

constructor(
    address _morpho,
    address _curvePool,
    address _usdc,
    address _plDxyBear
) Ownable(msg.sender);

Parameters

NameTypeDescription
_morphoaddressMorpho Blue protocol address.
_curvePooladdressCurve USDC/plDXY-BEAR pool address.
_usdcaddressUSDC token address.
_plDxyBearaddressplDXY-BEAR token address.

pause

Pause the router. Blocks openLeverage and closeLeverage.

function pause() external onlyOwner;

unpause

Unpause the router.

function unpause() external onlyOwner;

getActualDebt

Returns the user’s current debt in this market (includes accrued interest).

function getActualDebt(
    address user
) external view returns (uint256 debt);

Parameters

NameTypeDescription
useraddressThe address to query debt for.

Returns

NameTypeDescription
debtuint256The actual debt amount in USDC (rounded up).

getCollateral

Returns the user’s collateral in this market.

function getCollateral(
    address user
) external view returns (uint256 collateral);

Parameters

NameTypeDescription
useraddressThe address to query collateral for.

Returns

NameTypeDescription
collateraluint256The collateral amount in staked token shares.

_marketId

Computes market ID from marketParams.

function _marketId() internal view returns (bytes32);

_getActualDebt

Computes actual debt from Morpho position, rounded up to ensure full repayment.

function _getActualDebt(
    address user
) internal view returns (uint256);

_getBorrowShares

Returns user’s borrow shares from Morpho position.

function _getBorrowShares(
    address user
) internal view returns (uint256);

_getCollateral

Returns user’s collateral from Morpho position.

function _getCollateral(
    address user
) internal view returns (uint256);

Errors

LeverageRouterBase__ZeroAddress

Thrown when zero address provided.

error LeverageRouterBase__ZeroAddress();

LeverageRouterBase__ZeroPrincipal

Thrown when principal is zero.

error LeverageRouterBase__ZeroPrincipal();

LeverageRouterBase__ZeroCollateral

Thrown when collateral is zero.

error LeverageRouterBase__ZeroCollateral();

LeverageRouterBase__Expired

Thrown when deadline has passed.

error LeverageRouterBase__Expired();

LeverageRouterBase__LeverageTooLow

Thrown when leverage multiplier <= 1x.

error LeverageRouterBase__LeverageTooLow();

LeverageRouterBase__SlippageExceedsMax

Thrown when slippage exceeds MAX_SLIPPAGE_BPS.

error LeverageRouterBase__SlippageExceedsMax();

LeverageRouterBase__NotAuthorized

Thrown when user hasn’t authorized router in Morpho.

error LeverageRouterBase__NotAuthorized();

LeverageRouterBase__InsufficientOutput

Thrown when swap output is insufficient.

error LeverageRouterBase__InsufficientOutput();

LeverageRouterBase__InvalidCurvePrice

Thrown when Curve price query returns zero.

error LeverageRouterBase__InvalidCurvePrice();

LeverageRouterBase__SplitterNotActive

Thrown when Splitter is not active.

error LeverageRouterBase__SplitterNotActive();

LeverageRouterBase__ZeroAmount

Thrown when amount is zero.

error LeverageRouterBase__ZeroAmount();

LeverageRouterBase__NoPosition

Thrown when user has no position in Morpho.

error LeverageRouterBase__NoPosition();

LeverageRouterBase__Unhealthy

Thrown when withdrawal would make position unhealthy.

error LeverageRouterBase__Unhealthy();

LeverageRouterBase__AmountTooSmall

Thrown when amount is too small after conversion.

error LeverageRouterBase__AmountTooSmall();

LeverageRouterBase__PermitFailed

error LeverageRouterBase__PermitFailed();

LeverageRouterBase__BelowMinAmountOut

Thrown when output is below user-specified minimum (MEV protection).

error LeverageRouterBase__BelowMinAmountOut();

Contents

AggregatorV3Interface

Git Source

Title: AggregatorV3Interface

Chainlink price feed interface.

Standard interface for Chainlink oracles. See https://docs.chain.link/data-feeds.

Functions

decimals

Returns the number of decimals in the price.

function decimals() external view returns (uint8);

description

Returns a human-readable description of the feed.

function description() external view returns (string memory);

version

Returns the feed version number.

function version() external view returns (uint256);

getRoundData

Returns historical round data.

function getRoundData(
    uint80 _roundId
)
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

Parameters

NameTypeDescription
_roundIduint80The round ID to query.

Returns

NameTypeDescription
roundIduint80The round ID.
answerint256The price answer.
startedAtuint256Timestamp when round started.
updatedAtuint256Timestamp of last update.
answeredInRounduint80The round in which answer was computed.

latestRoundData

Returns the latest round data.

function latestRoundData()
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

Returns

NameTypeDescription
roundIduint80The current round ID.
answerint256The latest price.
startedAtuint256Timestamp when round started.
updatedAtuint256Timestamp of last update.
answeredInRounduint80The round in which answer was computed.

ICurveGauge

Git Source

Functions

lp_token

function lp_token() external view returns (address);

deposit

function deposit(
    uint256 amount
) external;

withdraw

function withdraw(
    uint256 amount
) external;

claim_rewards

function claim_rewards() external;

balanceOf

function balanceOf(
    address
) external view returns (uint256);

ICurveMinter

Git Source

Functions

mint

function mint(
    address gauge
) external;

ICurvePool

Git Source

Title: ICurvePool

Interface for Curve StableSwap pools.

Used for USDC/plDXY-BEAR swaps. Indices: USDC=0, plDXY-BEAR=1.

Functions

get_dy

Calculates expected output for a swap.

function get_dy(
    uint256 i,
    uint256 j,
    uint256 dx
) external view returns (uint256);

Parameters

NameTypeDescription
iuint256Input token index.
juint256Output token index.
dxuint256Input amount.

Returns

NameTypeDescription
<none>uint256Expected output amount.

exchange

Executes a token swap.

function exchange(
    uint256 i,
    uint256 j,
    uint256 dx,
    uint256 min_dy
) external payable returns (uint256);

Parameters

NameTypeDescription
iuint256Input token index.
juint256Output token index.
dxuint256Input amount.
min_dyuint256Minimum output (slippage protection).

Returns

NameTypeDescription
<none>uint256Actual output amount.

price_oracle

Returns EMA oracle price (18 decimals).

function price_oracle() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Price of token1 in terms of token0.

ICurveTwocrypto

Git Source

Functions

add_liquidity

function add_liquidity(
    uint256[2] calldata amounts,
    uint256 min_mint_amount
) external returns (uint256);

remove_liquidity_one_coin

function remove_liquidity_one_coin(
    uint256 token_amount,
    uint256 i,
    uint256 min_amount
) external returns (uint256);

remove_liquidity

function remove_liquidity(
    uint256 amount,
    uint256[2] calldata min_amounts
) external returns (uint256[2] memory);

get_virtual_price

function get_virtual_price() external view returns (uint256);

lp_price

function lp_price() external view returns (uint256);

calc_token_amount

function calc_token_amount(
    uint256[2] calldata amounts,
    bool deposit
) external view returns (uint256);

calc_withdraw_one_coin

function calc_withdraw_one_coin(
    uint256 token_amount,
    uint256 i
) external view returns (uint256);

IInvarCoin

Git Source

Functions

donateUsdc

function donateUsdc(
    uint256 usdcAmount
) external;

totalAssets

function totalAssets() external view returns (uint256);

MarketParams

Git Source

Morpho Blue market configuration.

struct MarketParams {
address loanToken;
address collateralToken;
address oracle;
address irm;
uint256 lltv;
}

Properties

NameTypeDescription
loanTokenaddressAsset being borrowed.
collateralTokenaddressAsset used as collateral.
oracleaddressPrice oracle for collateral valuation.
irmaddressInterest rate model contract.
lltvuint256Liquidation loan-to-value ratio.

IMorpho

Git Source

Title: IMorpho

Minimal interface for Morpho Blue lending protocol.

See https://docs.morpho.org for full documentation.

Functions

setAuthorization

Set authorization for an address to act on behalf of the caller

function setAuthorization(
    address authorized,
    bool newIsAuthorized
) external;

isAuthorized

Check if an address is authorized to act on behalf of another

function isAuthorized(
    address authorizer,
    address authorized
) external view returns (bool);

createMarket

Create a new market

function createMarket(
    MarketParams memory marketParams
) external;

idToMarketParams

Get market ID from params

function idToMarketParams(
    bytes32 id
) external view returns (MarketParams memory);

supply

Supply loan assets to a Morpho market as a lender

function supply(
    MarketParams memory marketParams,
    uint256 assets,
    uint256 shares,
    address onBehalfOf,
    bytes calldata data
) external returns (uint256 assetsSupplied, uint256 sharesSupplied);

withdraw

Withdraw loan assets from a Morpho market as a lender

function withdraw(
    MarketParams memory marketParams,
    uint256 assets,
    uint256 shares,
    address onBehalfOf,
    address receiver
) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);

supplyCollateral

Supply collateral to a Morpho market as a borrower

function supplyCollateral(
    MarketParams memory marketParams,
    uint256 assets,
    address onBehalfOf,
    bytes calldata data
) external;

withdrawCollateral

Withdraw collateral from a Morpho market as a borrower

function withdrawCollateral(
    MarketParams memory marketParams,
    uint256 assets,
    address onBehalfOf,
    address receiver
) external;

borrow

Borrow assets from a Morpho market

function borrow(
    MarketParams memory marketParams,
    uint256 assets,
    uint256 shares,
    address onBehalfOf,
    address receiver
) external returns (uint256 assetsBorrowed, uint256 sharesIssued);

repay

Repay borrowed assets to a Morpho market

function repay(
    MarketParams memory marketParams,
    uint256 assets,
    uint256 shares,
    address onBehalfOf,
    bytes calldata data
) external returns (uint256 assetsRepaid, uint256 sharesRepaid);

accrueInterest

Accrue interest for a market

function accrueInterest(
    MarketParams memory marketParams
) external;

liquidate

Liquidate an unhealthy position

function liquidate(
    MarketParams memory marketParams,
    address borrower,
    uint256 seizedAssets,
    uint256 repaidShares,
    bytes calldata data
) external returns (uint256 assetsSeized, uint256 assetsRepaid);

Parameters

NameTypeDescription
marketParamsMarketParamsThe market parameters
borroweraddressThe address of the borrower to liquidate
seizedAssetsuint256The amount of collateral to seize
repaidSharesuint256The amount of debt shares to repay (alternative to seizedAssets)
databytesCallback data

flashLoan

Execute a flash loan

Morpho flash loans are fee-free. Callback must repay exact amount.

function flashLoan(
    address token,
    uint256 assets,
    bytes calldata data
) external;

Parameters

NameTypeDescription
tokenaddressThe token to flash loan
assetsuint256The amount of tokens to flash loan
databytesArbitrary data to pass to the callback

position

Get position data for a user in a market

function position(
    bytes32 id,
    address user
) external view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);

market

Get market data

function market(
    bytes32 id
)
    external
    view
    returns (
        uint128 totalSupplyAssets,
        uint128 totalSupplyShares,
        uint128 totalBorrowAssets,
        uint128 totalBorrowShares,
        uint128 lastUpdate,
        uint128 fee
    );

Structs

MarketState

Market state for IRM calculations.

struct MarketState {
    uint128 totalSupplyAssets;
    uint128 totalSupplyShares;
    uint128 totalBorrowAssets;
    uint128 totalBorrowShares;
    uint128 lastUpdate;
    uint128 fee;
}

IMorphoFlashLoanCallback

Git Source

Title: IMorphoFlashLoanCallback

Callback interface for Morpho flash loan receivers.

Functions

onMorphoFlashLoan

Called by Morpho during flash loan execution.

function onMorphoFlashLoan(
    uint256 assets,
    bytes calldata data
) external;

Parameters

NameTypeDescription
assetsuint256Amount of tokens borrowed.
databytesArbitrary data passed through from flashLoan call.

PythStructs

Git Source

Title: Pyth Price Structs

Structs

Price

struct Price {
    int64 price;
    uint64 conf;
    int32 expo;
    uint256 publishTime;
}

IPyth

Git Source

Title: Pyth Network Interface (minimal)

Minimal interface for reading Pyth price feeds.

Functions

getPriceUnsafe

Returns the price without staleness checks.

function getPriceUnsafe(
    bytes32 id
) external view returns (PythStructs.Price memory price);

Parameters

NameTypeDescription
idbytes32The Pyth price feed ID.

Returns

NameTypeDescription
pricePythStructs.PriceThe price data.

getPriceNoOlderThan

Returns the price if it’s no older than age seconds.

function getPriceNoOlderThan(
    bytes32 id,
    uint256 age
) external view returns (PythStructs.Price memory price);

Parameters

NameTypeDescription
idbytes32The Pyth price feed ID.
ageuint256Maximum acceptable age in seconds.

Returns

NameTypeDescription
pricePythStructs.PriceThe price data.

updatePriceFeeds

Updates price feeds with signed data from Pyth.

function updatePriceFeeds(
    bytes[] calldata updateData
) external payable;

Parameters

NameTypeDescription
updateDatabytes[]Array of price update data.

getUpdateFee

Returns the fee required to update price feeds.

function getUpdateFee(
    bytes[] calldata updateData
) external view returns (uint256 feeAmount);

Parameters

NameTypeDescription
updateDatabytes[]Array of price update data.

Returns

NameTypeDescription
feeAmountuint256The required fee in wei.

IRewardDistributor

Git Source

Title: IRewardDistributor

Interface for the RewardDistributor contract that allocates staking rewards based on price discrepancy between oracle and Curve pool.

Functions

distributeRewards

Permissionless function to distribute accumulated USDC rewards.

Calculates price discrepancy, acquires tokens, and donates to vaults.

function distributeRewards() external returns (uint256 callerReward);

Returns

NameTypeDescription
callerRewarduint256Amount of USDC sent to caller as incentive.

distributeRewardsWithPriceUpdate

Distributes rewards after updating the Pyth oracle price.

Bundles Pyth price update with reward distribution. Pass empty array if no update needed.

function distributeRewardsWithPriceUpdate(
    bytes[] calldata pythUpdateData
) external payable returns (uint256 callerReward);

Parameters

NameTypeDescription
pythUpdateDatabytes[]Price update data from Pyth Hermes API.

Returns

NameTypeDescription
callerRewarduint256Amount of USDC sent to caller as incentive.

previewDistribution

Preview the distribution without executing.

function previewDistribution()
    external
    view
    returns (uint256 bearPct, uint256 bullPct, uint256 usdcBalance, uint256 callerReward);

Returns

NameTypeDescription
bearPctuint256Expected percentage to BEAR stakers (basis points).
bullPctuint256Expected percentage to BULL stakers (basis points).
usdcBalanceuint256Current USDC balance available for distribution.
callerRewarduint256Expected caller reward.

Events

RewardsDistributed

Emitted when rewards are distributed to staking vaults.

event RewardsDistributed(
    uint256 bearAmount, uint256 bullAmount, uint256 invarUsdcAmount, uint256 bearPct, uint256 bullPct
);

Parameters

NameTypeDescription
bearAmountuint256Amount of plDXY-BEAR donated to StakedBear.
bullAmountuint256Amount of plDXY-BULL donated to StakedBull.
invarUsdcAmountuint256Amount of USDC donated to InvarCoin.
bearPctuint256Percentage of rewards allocated to BEAR stakers (basis points).
bullPctuint256Percentage of rewards allocated to BULL stakers (basis points).

Errors

RewardDistributor__DistributionTooSoon

Thrown when distribution is attempted before cooldown expires.

error RewardDistributor__DistributionTooSoon();

RewardDistributor__NoRewards

Thrown when there are no rewards to distribute.

error RewardDistributor__NoRewards();

RewardDistributor__SplitterNotActive

Thrown when the SyntheticSplitter is not in ACTIVE status.

error RewardDistributor__SplitterNotActive();

RewardDistributor__ZeroAddress

Thrown when a constructor parameter is zero address.

error RewardDistributor__ZeroAddress();

RewardDistributor__RefundFailed

Thrown when ETH refund to caller fails.

error RewardDistributor__RefundFailed();

RewardDistributor__InvalidPrice

Thrown when oracle returns zero or negative price.

error RewardDistributor__InvalidPrice();

ISyntheticSplitter

Git Source

Title: ISyntheticSplitter

Minimal interface for external contracts to interact with SyntheticSplitter.

Used by ZapRouter and other integrations.

Functions

mint

Deposits collateral to mint equal amounts of plDXY-BEAR and plDXY-BULL tokens.

Requires approval on USDC. Amount is in 18-decimal token units.

function mint(
    uint256 amount
) external;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to mint.

mintWithPermit

Deposits collateral to mint tokens with a USDC permit signature (gasless approval).

function mintWithPermit(
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to mint.
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

burn

Burns equal amounts of plDXY-BEAR and plDXY-BULL tokens to retrieve collateral.

Works when not liquidated. May be restricted when paused and insolvent.

function burn(
    uint256 amount
) external;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to burn.

emergencyRedeem

Emergency exit after liquidation. Burns plDXY-BEAR for its full CAP value.

Only works when protocol is liquidated (price >= CAP).

function emergencyRedeem(
    uint256 amount
) external;

Parameters

NameTypeDescription
amountuint256The amount of plDXY-BEAR tokens to burn.

currentStatus

Returns the current protocol lifecycle status.

function currentStatus() external view returns (Status);

Returns

NameTypeDescription
<none>StatusThe current Status enum value.

CAP

Returns the protocol CAP price (8 decimals, oracle format).

function CAP() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The CAP value in 8 decimal format (e.g., 2e8 = $2.00).

liquidationTimestamp

Returns the timestamp when the protocol was liquidated.

function liquidationTimestamp() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The liquidation timestamp (0 if not liquidated).

treasury

Returns the treasury address.

function treasury() external view returns (address);

Returns

NameTypeDescription
<none>addressThe treasury address.

Enums

Status

Defines the current lifecycle state of the protocol.

enum Status {
    ACTIVE,
    PAUSED,
    SETTLED
}

Variants

NameDescription
ACTIVENormal operations. Minting and burning enabled.
PAUSEDSecurity pause. Minting disabled, burn may be restricted if insolvent.
SETTLEDEnd of life. Cap breached. Only emergencyRedeem enabled.

IYieldAdapter

Git Source

Title: IYieldAdapter

Extended interface for yield adapters that support interest accrual.

Optional extension to IERC4626 for adapters with pending interest.

Functions

accrueInterest

Forces the underlying protocol to accrue pending interest.

Call before reading totalAssets() if exact values are needed for calculations.

function accrueInterest() external;

Contents

DecimalConstants

Git Source

Title: DecimalConstants

Shared decimal scaling constants for the Plether protocol.

Centralizes decimal conversions to prevent scaling bugs.

Constants

ONE_WAD

One unit with 18 decimals (standard ERC20/leverage scale).

uint256 internal constant ONE_WAD = 1e18;

ONE_USDC

One USDC (6 decimals).

uint256 internal constant ONE_USDC = 1e6;

USDC_TO_TOKEN_SCALE

USDC (6 dec) + Chainlink (8 dec) -> Token (18 dec): 10^20.

uint256 internal constant USDC_TO_TOKEN_SCALE = 1e20;

Chainlink (8 dec) -> Morpho (36 + loanDec - collateralDec = 24 dec): 10^16.

uint256 internal constant CHAINLINK_TO_MORPHO_SCALE = 1e16;

Chainlink (8 dec) -> Token (18 dec): 10^10.

uint256 internal constant CHAINLINK_TO_TOKEN_SCALE = 1e10;

IIrm

Git Source

Title: IIrm

Minimal interface for Morpho Blue Interest Rate Models.

Functions

borrowRateView

Returns the borrow rate per second (scaled by 1e18).

function borrowRateView(
    MarketParams memory marketParams,
    IMorpho.MarketState memory market
) external view returns (uint256);

MorphoBalancesLib

Git Source

Title: MorphoBalancesLib

Library to compute expected Morpho balances including pending interest.

Mirrors Morpho Blue’s internal interest accrual logic for accurate view functions.

Constants

WAD

uint256 internal constant WAD = 1e18;

Functions

expectedTotalSupplyAssets

Computes expected total supply assets including pending interest.

function expectedTotalSupplyAssets(
    IMorpho morpho,
    MarketParams memory marketParams
) internal view returns (uint256 expectedSupplyAssets);

Parameters

NameTypeDescription
morphoIMorphoMorpho Blue contract.
marketParamsMarketParamsMarket parameters.

Returns

NameTypeDescription
expectedSupplyAssetsuint256Total supply assets after pending interest accrual.

expectedSupplyAssets

Converts supply shares to expected assets including pending interest.

function expectedSupplyAssets(
    IMorpho morpho,
    MarketParams memory marketParams,
    uint256 shares
) internal view returns (uint256 assets);

Parameters

NameTypeDescription
morphoIMorphoMorpho Blue contract.
marketParamsMarketParamsMarket parameters.
sharesuint256Supply shares to convert.

Returns

NameTypeDescription
assetsuint256Expected asset amount.

OracleLib

Git Source

Title: OracleLib

Library for common oracle validation patterns.

Provides reusable functions for sequencer checks, staleness validation, and price validation.

Functions

checkSequencer

Check if the L2 sequencer is up and grace period has passed.

Skips check if sequencerFeed is address(0) (e.g., on L1 or testnets).

function checkSequencer(
    AggregatorV3Interface sequencerFeed,
    uint256 gracePeriod
) internal view;

Parameters

NameTypeDescription
sequencerFeedAggregatorV3InterfaceThe Chainlink sequencer uptime feed.
gracePerioduint256The grace period in seconds after sequencer comes back up.

checkStaleness

Check if the oracle price is stale.

function checkStaleness(
    uint256 updatedAt,
    uint256 timeout
) internal view;

Parameters

NameTypeDescription
updatedAtuint256The timestamp when the price was last updated.
timeoutuint256The maximum age in seconds for a valid price.

checkStalenessAt

Check staleness relative to a specific reference timestamp instead of block.timestamp.

function checkStalenessAt(
    uint256 updatedAt,
    uint256 timeout,
    uint256 referenceTime
) internal pure;

Parameters

NameTypeDescription
updatedAtuint256The timestamp when the price was last updated.
timeoutuint256The maximum age in seconds for a valid price.
referenceTimeuint256The timestamp to measure staleness against.

verifyHistoricalPrice

Verifies a caller-provided hint round is the correct price at a target timestamp.

Avoids backward traversal that breaks on Chainlink phase boundaries.

function verifyHistoricalPrice(
    AggregatorV3Interface feed,
    uint256 targetTimestamp,
    uint80 hintRoundId
) internal view returns (int256 price, uint256 updatedAt);

Parameters

NameTypeDescription
feedAggregatorV3InterfaceThe Chainlink price feed.
targetTimestampuint256The timestamp to look up the price for.
hintRoundIduint80The round ID that the caller claims was active at targetTimestamp.

Returns

NameTypeDescription
priceint256The price at the target timestamp.
updatedAtuint256The timestamp of the round found.

getValidatedPrice

Get a validated price from an oracle with staleness and sequencer checks.

Reverts on zero or negative prices to prevent operations during oracle failures.

function getValidatedPrice(
    AggregatorV3Interface oracle,
    AggregatorV3Interface sequencerFeed,
    uint256 gracePeriod,
    uint256 timeout
) internal view returns (uint256 price);

Parameters

NameTypeDescription
oracleAggregatorV3InterfaceThe price oracle.
sequencerFeedAggregatorV3InterfaceThe sequencer uptime feed (can be address(0) to skip).
gracePerioduint256The sequencer grace period in seconds.
timeoutuint256The staleness timeout in seconds.

Returns

NameTypeDescription
priceuint256The validated price.

tryGetValidatedPrice

Non-reverting variant of getValidatedPrice for best-effort oracle reads.

function tryGetValidatedPrice(
    AggregatorV3Interface oracle,
    AggregatorV3Interface sequencerFeed,
    uint256 gracePeriod,
    uint256 timeout
) internal view returns (bool success, uint256 price);

Returns

NameTypeDescription
successboolTrue if the price passed all validation checks.
priceuint256The validated price (0 if success is false).

Errors

OracleLib__SequencerDown

error OracleLib__SequencerDown();

OracleLib__SequencerGracePeriod

error OracleLib__SequencerGracePeriod();

OracleLib__StalePrice

error OracleLib__StalePrice();

OracleLib__InvalidPrice

error OracleLib__InvalidPrice();

OracleLib__NoPriceAtExpiry

error OracleLib__NoPriceAtExpiry();

OracleLib__InsufficientGas

error OracleLib__InsufficientGas();

Contents

DOVZapRouter

Git Source

Inherits: FlashLoanBase, ReentrancyGuard, Ownable2Step

Title: DOVZapRouter

Coordinates USDC→splDXY zaps across BEAR and BULL DOVs.

Mints pairs for the overlapping USDC amount (zero slippage), routes excess through Curve or flash mint.

Note: security-contact: contact@plether.com

Constants

USDC_INDEX

uint256 public constant USDC_INDEX = 0;

PLDXY_BEAR_INDEX

uint256 public constant PLDXY_BEAR_INDEX = 1;

SAFETY_BUFFER_BPS

uint256 public constant SAFETY_BUFFER_BPS = 50;

SPLITTER

ISyntheticSplitter public immutable SPLITTER;

CURVE_POOL

ICurvePool public immutable CURVE_POOL;

USDC

IERC20 public immutable USDC;

PLDXY_BEAR

IERC20 public immutable PLDXY_BEAR;

PLDXY_BULL

IERC20 public immutable PLDXY_BULL;

STAKED_BEAR

IERC4626 public immutable STAKED_BEAR;

STAKED_BULL

IERC4626 public immutable STAKED_BULL;

BEAR_DOV

PletherDOV public immutable BEAR_DOV;

BULL_DOV

PletherDOV public immutable BULL_DOV;

CAP

uint256 public immutable CAP;

CAP_PRICE

uint256 public immutable CAP_PRICE;

Functions

constructor

constructor(
    address _splitter,
    address _curvePool,
    address _usdc,
    address _plDxyBear,
    address _plDxyBull,
    address _stakedBear,
    address _stakedBull,
    address _bearDov,
    address _bullDov
) Ownable(msg.sender);

coordinatedZapAndStartEpochs

Pulls USDC from both DOVs, mints matched pairs, routes excess, starts epoch auctions.

function coordinatedZapAndStartEpochs(
    EpochParams calldata bearParams,
    EpochParams calldata bullParams,
    uint256 minBearSwapOut,
    uint256 minBullSwapOut
) external onlyOwner nonReentrant;

_flashZapBull

function _flashZapBull(
    uint256 usdcAmount,
    uint256 minSwapOut
) internal;

onFlashLoan

function onFlashLoan(
    address initiator,
    address,
    uint256 amount,
    uint256 fee,
    bytes calldata data
) external override returns (bytes32);

onMorphoFlashLoan

function onMorphoFlashLoan(
    uint256,
    bytes calldata
) external pure override;

Events

CoordinatedZap

event CoordinatedZap(uint256 bearUsdc, uint256 bullUsdc, uint256 matchedAmount);

Errors

DOVZapRouter__SolvencyBreach

error DOVZapRouter__SolvencyBreach();

DOVZapRouter__BearPriceAboveCap

error DOVZapRouter__BearPriceAboveCap();

Structs

EpochParams

struct EpochParams {
    uint256 strike;
    uint256 expiry;
    uint256 maxPremium;
    uint256 minPremium;
    uint256 duration;
}

ISettlementOracle

Git Source

Functions

getSettlementPrices

function getSettlementPrices(
    uint256 expiry,
    uint80[] calldata roundHints
) external view returns (uint256 bearPrice, uint256 bullPrice);

IOptionToken

Git Source

Functions

initialize

function initialize(
    string memory name,
    string memory symbol,
    address marginEngine
) external;

mint

function mint(
    address to,
    uint256 amount
) external;

burn

function burn(
    address from,
    uint256 amount
) external;

totalSupply

function totalSupply() external view returns (uint256);

MarginEngine

Git Source

Inherits: ReentrancyGuard, AccessControl

Title: MarginEngine

Core options clearinghouse for Plether DOVs.

Enforces 100% margin requirements and Fractional In-Kind Settlement via StakedTokens.

Note: security-contact: contact@plether.com

Constants

SERIES_CREATOR_ROLE

bytes32 public constant SERIES_CREATOR_ROLE = keccak256("SERIES_CREATOR_ROLE");

SPLITTER

ISyntheticSplitter public immutable SPLITTER;

ORACLE

ISettlementOracle public immutable ORACLE;

STAKED_BEAR

IERC4626 public immutable STAKED_BEAR;

STAKED_BULL

IERC4626 public immutable STAKED_BULL;

OPTION_IMPLEMENTATION

address public immutable OPTION_IMPLEMENTATION;

CAP

uint256 public immutable CAP;

State Variables

nextSeriesId

uint256 public nextSeriesId = 1;

series

mapping(uint256 => Series) public series;

seriesCreator

mapping(uint256 => address) public seriesCreator;

writerLockedShares

mapping(uint256 => mapping(address => uint256)) public writerLockedShares;

writerOptions

mapping(uint256 => mapping(address => uint256)) public writerOptions;

totalSeriesShares

mapping(uint256 => uint256) public totalSeriesShares;

totalSeriesMinted

mapping(uint256 => uint256) public totalSeriesMinted;

totalSeriesExercisedShares

mapping(uint256 => uint256) public totalSeriesExercisedShares;

settlementTimestamp

mapping(uint256 => uint256) public settlementTimestamp;

Functions

constructor

constructor(
    address _splitter,
    address _oracle,
    address _stakedBear,
    address _stakedBull,
    address _optionImplementation
);

createSeries

Admin function to deploy a new Option Token Series via EIP-1167.

function createSeries(
    bool isBull,
    uint256 strike,
    uint256 expiry,
    string memory name,
    string memory symbol
) external onlyRole(SERIES_CREATOR_ROLE) returns (uint256 seriesId);

mintOptions

Writers (DOVs) call this to lock splDXY yield-bearing shares and mint options.

Ensures exact 1:1 backing of the underlying asset capacity.

function mintOptions(
    uint256 seriesId,
    uint256 optionsAmount
) external nonReentrant;

settle

Locks the settlement price and exchange rate at expiration.

Callable by anyone. Triggers “Early Acceleration” if protocol liquidates mid-cycle.

function settle(
    uint256 seriesId,
    uint80[] calldata roundHints
) external;

Parameters

NameTypeDescription
seriesIduint256
roundHintsuint80[]Chainlink round IDs for oracle lookup (one per feed component).

adminSettle

Admin fallback for oracle failures — settles with a manually provided price.

2-day grace period after expiry gives the oracle time to recover first.

function adminSettle(
    uint256 seriesId,
    uint256 settlementPrice
) external onlyRole(DEFAULT_ADMIN_ROLE);

exercise

Buyers burn ITM Options to extract their fractional payout of the collateral pool.

Share conversion uses the settlement-time rate for economically correct payouts.

function exercise(
    uint256 seriesId,
    uint256 optionsAmount
) external nonReentrant;

unlockCollateral

Writers unlock their remaining splDXY shares post-settlement.

Uses global debt pro-rata to stay consistent with the exercise cap. globalDebtShares represents the theoretical max debt assuming 100% exercise. If some option holders don’t exercise, their unclaimed share of globalDebtShares remains locked until sweepUnclaimedShares is called after 90 days.

function unlockCollateral(
    uint256 seriesId
) external nonReentrant;

sweepUnclaimedShares

Sweeps unclaimed exercise shares 90 days after settlement.

Returns shares reserved for unexercised ITM options to the admin for distribution.

function sweepUnclaimedShares(
    uint256 seriesId
) external onlyRole(DEFAULT_ADMIN_ROLE) nonReentrant;

_getGlobalDebtShares

function _getGlobalDebtShares(
    Series storage s,
    uint256 totalMinted,
    uint256 totalShares
) private view returns (uint256 globalDebtShares);

_snapshotShareRate

function _snapshotShareRate(
    Series storage s
) private view returns (uint256);

_transferVaultShares

function _transferVaultShares(
    bool isBull,
    address to,
    uint256 amount
) private;

Events

SeriesCreated

event SeriesCreated(uint256 indexed seriesId, address optionToken, bool isBull, uint256 strike, uint256 expiry);

OptionsMinted

event OptionsMinted(uint256 indexed seriesId, address indexed writer, uint256 optionsAmount, uint256 sharesLocked);

SeriesSettled

event SeriesSettled(uint256 indexed seriesId, uint256 settlementPrice, uint256 settlementShareRate);

OptionsExercised

event OptionsExercised(
    uint256 indexed seriesId, address indexed buyer, uint256 optionsAmount, uint256 sharesReceived
);

CollateralUnlocked

event CollateralUnlocked(
    uint256 indexed seriesId, address indexed writer, uint256 optionsAmount, uint256 sharesReturned
);

UnclaimedSharesSwept

event UnclaimedSharesSwept(uint256 indexed seriesId, uint256 sharesSwept);

Errors

MarginEngine__InvalidParams

error MarginEngine__InvalidParams();

MarginEngine__Expired

error MarginEngine__Expired();

MarginEngine__NotExpired

error MarginEngine__NotExpired();

MarginEngine__AlreadySettled

error MarginEngine__AlreadySettled();

MarginEngine__NotSettled

error MarginEngine__NotSettled();

MarginEngine__OptionIsOTM

error MarginEngine__OptionIsOTM();

MarginEngine__ZeroAmount

error MarginEngine__ZeroAmount();

MarginEngine__SplitterNotActive

error MarginEngine__SplitterNotActive();

MarginEngine__AdminSettleTooEarly

error MarginEngine__AdminSettleTooEarly();

MarginEngine__SweepTooEarly

error MarginEngine__SweepTooEarly();

MarginEngine__Unauthorized

error MarginEngine__Unauthorized();

Structs

Series

struct Series {
    bool isBull;
    uint256 strike;
    uint256 expiry;
    address optionToken;
    uint256 settlementPrice;
    uint256 settlementShareRate;
    bool isSettled;
}

OptionToken

Git Source

Title: OptionToken

EIP-1167 Minimal Proxy Implementation for Option Series.

Constants

decimals

uint8 public constant decimals = 18;

State Variables

name

string public name;

symbol

string public symbol;

totalSupply

uint256 public totalSupply;

balanceOf

mapping(address => uint256) public balanceOf;

allowance

mapping(address => mapping(address => uint256)) public allowance;

marginEngine

address public marginEngine;

_initialized

bool private _initialized;

Functions

constructor

constructor();

onlyEngine

modifier onlyEngine();

initialize

Initialize the proxy (called once by MarginEngine).

function initialize(
    string memory _name,
    string memory _symbol,
    address _marginEngine
) external;

mint

function mint(
    address to,
    uint256 amount
) external onlyEngine;

burn

function burn(
    address from,
    uint256 amount
) external onlyEngine;

approve

function approve(
    address spender,
    uint256 amount
) external returns (bool);

transfer

function transfer(
    address to,
    uint256 amount
) external returns (bool);

transferFrom

function transferFrom(
    address from,
    address to,
    uint256 amount
) external returns (bool);

Events

Transfer

event Transfer(address indexed from, address indexed to, uint256 value);

Approval

event Approval(address indexed owner, address indexed spender, uint256 value);

Initialized

event Initialized(string name, string symbol, address marginEngine);

Errors

OptionToken__AlreadyInitialized

error OptionToken__AlreadyInitialized();

OptionToken__Unauthorized

error OptionToken__Unauthorized();

OptionToken__InsufficientBalance

error OptionToken__InsufficientBalance();

OptionToken__InsufficientAllowance

error OptionToken__InsufficientAllowance();

OptionToken__ZeroAddress

error OptionToken__ZeroAddress();

IMarginEngine

Git Source

Functions

createSeries

function createSeries(
    bool isBull,
    uint256 strike,
    uint256 expiry,
    string memory name,
    string memory sym
) external returns (uint256);

mintOptions

function mintOptions(
    uint256 seriesId,
    uint256 optionsAmount
) external;

settle

function settle(
    uint256 seriesId,
    uint80[] calldata roundHints
) external;

unlockCollateral

function unlockCollateral(
    uint256 seriesId
) external;

exercise

function exercise(
    uint256 seriesId,
    uint256 optionsAmount
) external;

series

function series(
    uint256 seriesId
) external view returns (bool, uint256, uint256, address, uint256, uint256, bool);

SPLITTER

function SPLITTER() external view returns (address);

Errors

MarginEngine__ZeroAmount

error MarginEngine__ZeroAmount();

PletherDOV

Git Source

Inherits: ERC20, ReentrancyGuard, Ownable2Step

Title: PletherDOV

Automated Covered Call Vault for Plether synthetic assets.

Natively holds splDXY to prevent weekly AMM slippage. Implements on-chain Dutch Auctions.

Note: security-contact: contact@plether.com

Constants

MARGIN_ENGINE

IMarginEngine public immutable MARGIN_ENGINE;

STAKED_TOKEN

IERC4626 public immutable STAKED_TOKEN;

USDC

IERC20 public immutable USDC;

IS_BULL

bool public immutable IS_BULL;

State Variables

currentState

State public currentState = State.UNLOCKED;

currentEpochId

uint256 public currentEpochId = 0;

zapKeeper

address public zapKeeper;

epochs

mapping(uint256 => Epoch) public epochs;

pendingUsdcDeposits

uint256 public pendingUsdcDeposits;

userUsdcDeposits

mapping(address => uint256) public userUsdcDeposits;

userDepositEpoch

mapping(address => uint256) public userDepositEpoch;

epochDeposits

mapping(uint256 => EpochDeposits) public epochDeposits;

_preZapSplDXYBalance

uint256 internal _preZapSplDXYBalance;

_preZapDepositUsdc

uint256 internal _preZapDepositUsdc;

_preZapPremiumUsdc

uint256 internal _preZapPremiumUsdc;

_zapSnapshotTaken

bool internal _zapSnapshotTaken;

Functions

constructor

constructor(
    string memory _name,
    string memory _symbol,
    address _marginEngine,
    address _stakedToken,
    address _usdc,
    bool _isBull
) ERC20(_name, _symbol) Ownable(msg.sender);

initializeShares

Mints initial shares to the owner for seed capital already held by the vault.

Must be called before the first epoch if the vault holds pre-seeded splDXY.

function initializeShares() external onlyOwner;

deposit

Queue USDC to be deposited into the DOV at the start of the next epoch.

Auto-claims shares from any previous epoch deposit before recording the new one.

function deposit(
    uint256 amount
) external nonReentrant;

withdrawDeposit

Withdraw queued USDC that has not yet been processed into an epoch.

function withdrawDeposit(
    uint256 amount
) external nonReentrant;

claimShares

Claims DOV shares earned from a previous epoch’s processed deposit.

function claimShares() external nonReentrant;

withdraw

Redeems vault shares for proportional splDXY (and any premium USDC).

Only callable during UNLOCKED. Auto-claims pending deposit shares first.

function withdraw(
    uint256 shares
) external nonReentrant;

setZapKeeper

function setZapKeeper(
    address _keeper
) external onlyOwner;

releaseUsdcForZap

Releases all USDC held by this DOV to the caller (zapKeeper only).

Snapshots pre-zap state for share calculation in startEpochAuction.

function releaseUsdcForZap() external returns (uint256 amount);

startEpochAuction

Step 1: Rolls the vault into a new epoch, mints options, starts Dutch Auction.

If deposits are pending, releaseUsdcForZap must have been called first to snapshot pre-zap state. Deposit shares are minted proportionally based on the zap conversion.

function startEpochAuction(
    uint256 strike,
    uint256 expiry,
    uint256 maxPremium,
    uint256 minPremium,
    uint256 duration
) external nonReentrant;

getCurrentOptionPrice

Calculates the current linearly decaying price per option.

function getCurrentOptionPrice() public view returns (uint256);

fillAuction

Step 2: Market Makers call this to buy the entire batch of options.

Premium calculation: optionsMinted (18 decimals) * currentPremium (6 decimals) / 1e18 = totalPremiumUsdc (6 decimals). Relies on OptionToken.decimals() == 18.

function fillAuction() external nonReentrant;

cancelAuction

Cancels an expired auction that received no fill, returning the vault to UNLOCKED.

Also allows immediate cancellation when the Splitter has liquidated.

function cancelAuction() external nonReentrant;

exerciseUnsoldOptions

Exercises unsold option tokens held by the DOV after a cancelled auction.

Skips exercise for OTM options so keeper batch transactions don’t revert.

function exerciseUnsoldOptions(
    uint256 epochId
) external nonReentrant;

reclaimCollateral

Reclaims collateral from an unsold series after it has been settled.

function reclaimCollateral(
    uint256 epochId
) external nonReentrant;

settleEpoch

Step 3: At expiration, settles the series and unlocks remaining collateral.

function settleEpoch(
    uint80[] calldata roundHints
) external nonReentrant;

Parameters

NameTypeDescription
roundHintsuint80[]Chainlink round IDs for oracle lookup (one per feed component). Ignored if the series is already settled.

emergencyWithdraw

Recovers stranded funds after Splitter liquidation (protocol end-of-life).

Only callable by owner when the Splitter has permanently settled.

function emergencyWithdraw(
    IERC20 token
) external onlyOwner;

pendingSharesOf

Returns the number of shares a user can claim from a processed deposit.

function pendingSharesOf(
    address user
) external view returns (uint256);

totalVaultAssets

Returns the vault’s total assets excluding pending deposits.

function totalVaultAssets() external view returns (uint256 splDXYShares, uint256 usdcBalance);

_claimShares

Claims DOV shares for a user whose deposit was processed in a previous epoch.

function _claimShares(
    address user
) internal;

_calculatePendingShares

function _calculatePendingShares(
    address user
) private view returns (uint256);

_mintDepositShares

Computes and mints aggregate shares for all depositors whose USDC was zapped. Uses the pre-zap snapshot from releaseUsdcForZap to attribute splDXY proportionally between existing shareholders (premium) and new depositors (deposit USDC).

function _mintDepositShares() internal;

Events

DepositQueued

event DepositQueued(address indexed user, uint256 amount);

DepositWithdrawn

event DepositWithdrawn(address indexed user, uint256 amount);

EpochRolled

event EpochRolled(uint256 indexed epochId, uint256 seriesId, uint256 optionsMinted);

AuctionFilled

event AuctionFilled(uint256 indexed epochId, address indexed buyer, uint256 premiumPaid);

AuctionCancelled

event AuctionCancelled(uint256 indexed epochId);

EpochSettled

event EpochSettled(uint256 indexed epochId, uint256 collateralReturned);

EmergencyWithdraw

event EmergencyWithdraw(address indexed token, uint256 amount);

ZapKeeperSet

event ZapKeeperSet(address indexed keeper);

SharesInitialized

event SharesInitialized(address indexed owner, uint256 shares);

DepositSharesMinted

event DepositSharesMinted(uint256 indexed epochId, uint256 totalShares, uint256 totalDepositsUsdc);

SharesClaimed

event SharesClaimed(address indexed user, uint256 shares);

Withdrawn

event Withdrawn(address indexed user, uint256 shares, uint256 splDXYAmount, uint256 usdcAmount);

Errors

PletherDOV__WrongState

error PletherDOV__WrongState();

PletherDOV__ZeroAmount

error PletherDOV__ZeroAmount();

PletherDOV__AuctionEnded

error PletherDOV__AuctionEnded();

PletherDOV__AuctionNotExpired

error PletherDOV__AuctionNotExpired();

PletherDOV__SplitterNotSettled

error PletherDOV__SplitterNotSettled();

PletherDOV__InvalidParams

error PletherDOV__InvalidParams();

PletherDOV__InsufficientDeposit

error PletherDOV__InsufficientDeposit();

PletherDOV__DepositProcessed

error PletherDOV__DepositProcessed();

PletherDOV__Unauthorized

error PletherDOV__Unauthorized();

PletherDOV__AlreadyInitialized

error PletherDOV__AlreadyInitialized();

PletherDOV__NotInitialized

error PletherDOV__NotInitialized();

PletherDOV__DepositsNotZapped

error PletherDOV__DepositsNotZapped();

PletherDOV__NothingToClaim

error PletherDOV__NothingToClaim();

Structs

Epoch

struct Epoch {
    uint256 seriesId;
    uint256 optionsMinted;
    uint256 auctionStartTime;
    uint256 maxPremium; // Max USDC price per option (6 decimals)
    uint256 minPremium; // Min USDC price per option (6 decimals)
    uint256 auctionDuration;
    address winningMaker;
}

EpochDeposits

struct EpochDeposits {
    uint256 totalUsdc;
    uint256 sharesMinted;
}

Enums

State

enum State {
    UNLOCKED,
    AUCTIONING,
    LOCKED
}

Contents

BasketOracle

Git Source

Inherits: AggregatorV3Interface, Ownable2Step

Title: BasketOracle

Aggregates multiple Chainlink feeds into a normalized weighted plDXY basket price.

Price = Sum(Weight_i * Price_i / BasePrice_i). Normalization preserves intended currency weights.

Note: security-contact: contact@plether.com

Constants

DECIMALS

Chainlink standard decimals for fiat/USD pairs.

uint8 public constant DECIMALS = 8;

DESCRIPTION

Oracle description string.

string public constant DESCRIPTION = "plDXY Fixed Basket (Bounded)";

TIMELOCK_DELAY

Timelock delay for Curve pool updates (7 days).

uint256 public constant TIMELOCK_DELAY = 7 days;

MAX_DEVIATION_BPS

Maximum allowed deviation from Curve spot (basis points).

uint256 public immutable MAX_DEVIATION_BPS;

CAP

Protocol CAP price (8 decimals). Theoretical price is clamped to this before deviation check.

uint256 public immutable CAP;

State Variables

components

Array of currency components (EUR, JPY, GBP, CAD, SEK, CHF).

Component[] public components;

curvePool

Curve pool for deviation validation.

ICurvePool public curvePool;

pendingCurvePool

Pending Curve pool for timelock-protected updates.

address public pendingCurvePool;

hasPendingProposal

Whether a proposal is active (needed because address(0) is a valid proposal).

bool public hasPendingProposal;

curvePoolActivationTime

Timestamp when pending Curve pool can be finalized.

uint256 public curvePoolActivationTime;

Functions

constructor

Creates basket oracle with currency components.

constructor(
    address[] memory _feeds,
    uint256[] memory _quantities,
    uint256[] memory _basePrices,
    uint256 _maxDeviationBps,
    uint256 _cap,
    address _owner
) Ownable(_owner);

Parameters

NameTypeDescription
_feedsaddress[]Array of Chainlink feed addresses.
_quantitiesuint256[]Array of basket weights (1e18 precision).
_basePricesuint256[]Array of base prices for normalization (8 decimals).
_maxDeviationBpsuint256Maximum deviation from Curve (e.g., 200 = 2%).
_capuint256Protocol CAP price (8 decimals). Clamps theoretical price in deviation check.
_owneraddressAdmin address for Curve pool management.

setCurvePool

Sets the Curve pool for deviation validation (initial setup only).

function setCurvePool(
    address _curvePool
) external onlyOwner;

Parameters

NameTypeDescription
_curvePooladdressCurve USDC/plDXY-BEAR pool address.

proposeCurvePool

Proposes a new Curve pool (requires 7-day timelock).

function proposeCurvePool(
    address _newPool
) external onlyOwner;

Parameters

NameTypeDescription
_newPooladdressNew Curve pool address.

finalizeCurvePool

Finalizes the Curve pool update after timelock expires.

function finalizeCurvePool() external onlyOwner;

latestRoundData

Returns the aggregated basket price from all component feeds.

function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80);

Returns

NameTypeDescription
<none>uint80roundId Mock round ID (always 1).
<none>int256answer The calculated basket price in 8 decimals.
<none>uint256startedAt Oldest component updatedAt (no separate round start; same as updatedAt).
<none>uint256updatedAt Oldest component updatedAt (weakest link for staleness checks).
<none>uint80answeredInRound Mock answered round (always 1).

_checkDeviation

Validates basket price against Curve spot. Reverts on excessive deviation. Intentionally acts as a global circuit breaker: if Chainlink and Curve EMA diverge beyond MAX_DEVIATION_BPS, all consumers (SyntheticSplitter, MorphoOracle, StakedOracle) are frozen — including Morpho liquidations. This is the desired behavior: large divergence signals either a compromised feed or a manipulated pool, and freezing is safer than acting on potentially bad price data.

function _checkDeviation(
    uint256 theoreticalDxy8Dec
) internal view;

Parameters

NameTypeDescription
theoreticalDxy8Decuint256Computed basket price (8 decimals).

decimals

Returns oracle decimals (8).

function decimals() external pure returns (uint8);

description

Returns oracle description.

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

version

Returns oracle version (1).

function version() external pure returns (uint256);

getRoundData

Returns data for a specific round ID.

Only round ID 1 is supported (synthetic basket has no historical rounds).

function getRoundData(
    uint80 _roundId
) external view returns (uint80, int256, uint256, uint256, uint80);

Events

CurvePoolProposed

Emitted when a new Curve pool is proposed.

event CurvePoolProposed(address indexed newPool, uint256 activationTime);

CurvePoolUpdated

Emitted when Curve pool is updated.

event CurvePoolUpdated(address indexed oldPool, address indexed newPool);

Errors

BasketOracle__InvalidPrice

Thrown when a component feed returns invalid price.

error BasketOracle__InvalidPrice(address feed);

BasketOracle__LengthMismatch

Thrown when feeds and quantities arrays have different lengths.

error BasketOracle__LengthMismatch();

BasketOracle__PriceDeviation

Thrown when basket price deviates too far from Curve spot.

error BasketOracle__PriceDeviation(uint256 theoretical, uint256 spot);

BasketOracle__AlreadySet

Thrown when Curve pool is already configured.

error BasketOracle__AlreadySet();

BasketOracle__TimelockActive

Thrown when timelock period has not elapsed.

error BasketOracle__TimelockActive();

BasketOracle__InvalidProposal

Thrown when no pending proposal exists.

error BasketOracle__InvalidProposal();

BasketOracle__InvalidDeviation

Thrown when max deviation is zero.

error BasketOracle__InvalidDeviation();

BasketOracle__InvalidBasePrice

Thrown when a base price is zero.

error BasketOracle__InvalidBasePrice();

BasketOracle__InvalidWeights

Thrown when quantities don’t sum to 1e18.

error BasketOracle__InvalidWeights();

BasketOracle__InvalidRoundId

error BasketOracle__InvalidRoundId();

Structs

Component

Component feed with its basket weight and base price for normalization.

struct Component {
    AggregatorV3Interface feed;
    uint256 quantity;
    uint256 basePrice;
}

IMorphoOracle

Git Source

Interface for Morpho-compatible price oracles.

Functions

price

Returns price of 1 collateral unit in loan asset terms (Morpho scale: 36 + loanDec - colDec = 24 decimals).

function price() external view returns (uint256);

MorphoOracle

Git Source

Inherits: IMorphoOracle

Title: MorphoOracle

Adapts BasketOracle price to Morpho Blue’s oracle scale (24 decimals for USDC/plDXY).

Supports both plDXY-BEAR (direct) and plDXY-BULL (inverse) pricing.

Note: security-contact: contact@plether.com

Constants

BASKET_ORACLE

Source price feed (BasketOracle).

AggregatorV3Interface public immutable BASKET_ORACLE;

CAP

Protocol CAP price (8 decimals).

uint256 public immutable CAP;

IS_INVERSE

If true, returns CAP - Price (for plDXY-BULL).

bool public immutable IS_INVERSE;

STALENESS_TIMEOUT

Maximum age for valid oracle price.

uint256 public constant STALENESS_TIMEOUT = 24 hours;

Functions

constructor

Creates Morpho-compatible oracle wrapper.

constructor(
    address _basketOracle,
    uint256 _cap,
    bool _isInverse
);

Parameters

NameTypeDescription
_basketOracleaddressBasketOracle address.
_capuint256Protocol CAP (8 decimals, e.g., 2e8 = $2.00).
_isInverseboolTrue for plDXY-BULL (CAP - Price), false for plDXY-BEAR.

price

Returns collateral price in Morpho scale (24 decimals for USDC(6)/plDXY(18)).

Morpho expects: 36 + loanDecimals - collateralDecimals = 36 + 6 - 18 = 24. BEAR (IS_INVERSE=false): min(basketPrice, CAP) * CHAINLINK_TO_MORPHO_SCALE. BULL (IS_INVERSE=true): (CAP - basketPrice) * CHAINLINK_TO_MORPHO_SCALE. Returns 1 (not 0) when BULL price would be zero to avoid Morpho division errors.

function price() external view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Price of 1 plDXY token in USDC terms (24 decimals).

Errors

MorphoOracle__InvalidPrice

Thrown when source oracle returns zero or negative price.

error MorphoOracle__InvalidPrice();

MorphoOracle__StalePrice

Thrown when source oracle data is stale.

error MorphoOracle__StalePrice();

MorphoOracle__ZeroAddress

Thrown when zero address provided to constructor.

error MorphoOracle__ZeroAddress();

PythAdapter

Git Source

Inherits: AggregatorV3Interface

Title: PythAdapter

Adapts Pyth Network price feeds to Chainlink’s AggregatorV3Interface.

Pyth is pull-based: prices must be pushed on-chain before reading. This adapter reads the latest price and converts it to 8 decimals. Supports price inversion for feeds like USD/SEK → SEK/USD.

Note: security-contact: contact@plether.com

Constants

PYTH

IPyth public immutable PYTH;

PRICE_ID

bytes32 public immutable PRICE_ID;

MAX_STALENESS

uint256 public immutable MAX_STALENESS;

MAX_CONFIDENCE_BPS

uint256 public immutable MAX_CONFIDENCE_BPS;

INVERSE

bool public immutable INVERSE;

DECIMALS

uint8 public constant DECIMALS = 8;

State Variables

DESCRIPTION

string public DESCRIPTION;

Functions

constructor

constructor(
    address pyth_,
    bytes32 priceId_,
    uint256 maxStaleness_,
    string memory description_,
    bool inverse_,
    uint256 maxConfidenceBps_
);

Parameters

NameTypeDescription
pyth_addressPyth contract address on this chain.
priceId_bytes32Pyth price feed ID (e.g., USD/SEK).
maxStaleness_uint256Maximum age of price in seconds before considered stale.
description_stringHuman-readable description (e.g., “SEK / USD”).
inverse_boolIf true, inverts the price (e.g., USD/SEK → SEK/USD).
maxConfidenceBps_uint256Maximum confidence interval as basis points of price (e.g., 500 = 5%).

latestRoundData

Returns the latest price data in Chainlink-compatible format.

Converts Pyth’s variable exponent to fixed 8 decimals. Reports block.timestamp as updatedAt (self-attestation): this adapter validates freshness internally against publishTime using MAX_STALENESS, then attests “price valid as of now.” Downstream consumers (BasketOracle, SyntheticSplitter) see a fresh timestamp and skip their own staleness check, avoiding double-timeout rejection during weekend forex market closures.

function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);

Returns

NameTypeDescription
<none>uint80roundId Always returns 1 (Pyth doesn’t use rounds).
<none>int256answer Price in 8 decimals.
<none>uint256startedAt Current block timestamp (adapter attestation time).
<none>uint256updatedAt Current block timestamp (adapter attestation time).
<none>uint80answeredInRound Always returns 1.

getRoundData

Returns data for a specific round ID.

Only round ID 1 is supported (Pyth doesn’t use rounds).

function getRoundData(
    uint80 _roundId
) external view returns (uint80, int256, uint256, uint256, uint80);

decimals

Returns the number of decimals (always 8 for compatibility).

function decimals() external pure returns (uint8);

description

Returns the price feed description.

function description() external view returns (string memory);

version

Returns the adapter version.

function version() external pure returns (uint256);

updatePrice

Updates the Pyth price feed with new data.

Anyone can call this to push fresh prices on-chain.

function updatePrice(
    bytes[] calldata updateData
) external payable;

Parameters

NameTypeDescription
updateDatabytes[]Price update data from Pyth’s Hermes API.

getUpdateFee

Returns the fee required to update the price.

function getUpdateFee(
    bytes[] calldata updateData
) external view returns (uint256 fee);

Parameters

NameTypeDescription
updateDatabytes[]Price update data to calculate fee for.

Returns

NameTypeDescription
feeuint256Fee in wei.

_convertTo8Decimals

Converts Pyth price to 8 decimals.

Pyth uses variable exponents (e.g., -8, -6). This normalizes to -8.

function _convertTo8Decimals(
    int64 price,
    int32 expo
) internal pure returns (int256);

Parameters

NameTypeDescription
priceint64Pyth price value.
expoint32Pyth exponent (negative for decimal places).

Returns

NameTypeDescription
<none>int256Normalized price in 8 decimals.

_invertTo8Decimals

Inverts Pyth price and converts to 8 decimals.

For converting USD/SEK to SEK/USD: 1 / (price * 10^expo) * 10^8

function _invertTo8Decimals(
    int64 price,
    int32 expo
) internal pure returns (int256);

Parameters

NameTypeDescription
priceint64Pyth price value.
expoint32Pyth exponent (negative for decimal places).

Returns

NameTypeDescription
<none>int256Inverted price in 8 decimals.

Errors

PythAdapter__StalePrice

error PythAdapter__StalePrice(uint256 publishTime, uint256 maxAge);

PythAdapter__InvalidPrice

error PythAdapter__InvalidPrice();

PythAdapter__ConfidenceTooWide

error PythAdapter__ConfidenceTooWide(uint64 conf, int64 price);

PythAdapter__InvalidRoundId

error PythAdapter__InvalidRoundId();

PythAdapter__RefundFailed

error PythAdapter__RefundFailed();

SettlementOracle

Git Source

Title: SettlementOracle

Pure theoretical oracle for option settlement.

Uses historical Chainlink round data to look up prices at expiry, eliminating the settlement window and preventing lookback MEV.

Note: security-contact: contact@plether.com

Constants

CAP

uint256 public immutable CAP;

SEQUENCER_UPTIME_FEED

AggregatorV3Interface public immutable SEQUENCER_UPTIME_FEED;

SEQUENCER_GRACE_PERIOD

uint256 public constant SEQUENCER_GRACE_PERIOD = 1 hours;

ORACLE_TIMEOUT

uint256 public constant ORACLE_TIMEOUT = 24 hours;

State Variables

components

Component[] public components;

Functions

constructor

constructor(
    address[] memory _feeds,
    uint256[] memory _quantities,
    uint256[] memory _basePrices,
    uint256 _cap,
    address _sequencerUptimeFeed
);

getSettlementPrices

Returns the pure theoretical settlement prices at a given expiry timestamp.

function getSettlementPrices(
    uint256 expiry,
    uint80[] calldata roundHints
) external view returns (uint256 bearPrice, uint256 bullPrice);

Parameters

NameTypeDescription
expiryuint256The timestamp at which to look up prices.
roundHintsuint80[]Caller-provided Chainlink round IDs (one per component) active at expiry.

Returns

NameTypeDescription
bearPriceuint256min(BasketPrice, CAP) in 8 decimals
bullPriceuint256CAP - bearPrice in 8 decimals

Errors

SettlementOracle__InvalidPrice

error SettlementOracle__InvalidPrice(address feed);

SettlementOracle__LengthMismatch

error SettlementOracle__LengthMismatch();

SettlementOracle__WrongHintCount

error SettlementOracle__WrongHintCount();

SettlementOracle__InvalidBasePrice

error SettlementOracle__InvalidBasePrice();

SettlementOracle__InvalidWeights

error SettlementOracle__InvalidWeights();

Structs

Component

struct Component {
    AggregatorV3Interface feed;
    uint256 quantity;
    uint256 basePrice;
}

IOracle

Git Source

Interface for price oracles.

Functions

price

Returns price of 1 collateral unit in loan asset terms.

function price() external view returns (uint256);

StakedOracle

Git Source

Inherits: IOracle

Title: StakedOracle

Prices ERC4626 vault shares by combining underlying price with exchange rate.

Price = UnderlyingPrice * ExchangeRate. Used for splDXY-BEAR/splDXY-BULL in Morpho.

Note: security-contact: contact@plether.com

Constants

VAULT

The staking vault (splDXY-BEAR or splDXY-BULL).

IERC4626 public immutable VAULT;

UNDERLYING_ORACLE

Oracle for the underlying plDXY token.

IOracle public immutable UNDERLYING_ORACLE;

SHARE_DECIMALS

Decimal multiplier for vault shares (accounts for ERC4626 decimal offset).

uint256 public immutable SHARE_DECIMALS;

Functions

constructor

Creates staked oracle for a vault.

constructor(
    address _vault,
    address _underlyingOracle
);

Parameters

NameTypeDescription
_vaultaddressERC4626 staking vault address.
_underlyingOracleaddressPrice oracle for the underlying plDXY token.

price

Returns price of 1 vault share including accrued yield.

function price() external view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Price in Morpho scale (24 decimals: underlying price * exchange rate).

Errors

StakedOracle__InvalidPrice

Thrown when underlying oracle returns zero price.

error StakedOracle__InvalidPrice();

StakedOracle__ZeroAddress

Thrown when zero address provided to constructor.

error StakedOracle__ZeroAddress();

Contents

Contents

AccountLensViewTypes

Git Source

Structs

AccountLedgerView

struct AccountLedgerView {
    uint256 settlementBalanceUsdc;
    uint256 freeSettlementUsdc;
    uint256 activePositionMarginUsdc;
    uint256 otherLockedMarginUsdc;
    uint256 executionEscrowUsdc;
    uint256 committedMarginUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 pendingOrderCount;
}

AccountLedgerSnapshot

struct AccountLedgerSnapshot {
    uint256 settlementBalanceUsdc;
    uint256 freeSettlementUsdc;
    uint256 activePositionMarginUsdc;
    uint256 otherLockedMarginUsdc;
    uint256 positionMarginBucketUsdc;
    uint256 committedOrderMarginBucketUsdc;
    uint256 reservedSettlementBucketUsdc;
    uint256 executionEscrowUsdc;
    uint256 committedMarginUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 pendingOrderCount;
    uint256 closeReachableUsdc;
    uint256 terminalReachableUsdc;
    uint256 accountEquityUsdc;
    uint256 freeBuyingPowerUsdc;
    bool hasPosition;
    CfdTypes.Side side;
    uint256 size;
    uint256 margin;
    uint256 entryPrice;
    int256 unrealizedPnlUsdc;
    int256 netEquityUsdc;
    bool liquidatable;
}

CfdEngineSettlementTypes

Git Source

Structs

PositionState

struct PositionState {
    bool deletePosition;
    uint256 size;
    uint256 entryPrice;
    uint256 maxProfitUsdc;
    uint64 lastUpdateTime;
    uint64 lastCarryTimestamp;
    int256 vpiAccrued;
    CfdTypes.Side side;
}

DeferredEngineViewTypes

Git Source

Structs

DeferredCreditStatus

Aggregate deferred-credit status under the current beneficiary-balance model.

struct DeferredCreditStatus {
    uint256 deferredTraderCreditUsdc;
    bool traderPayoutClaimableNow;
    uint256 deferredKeeperCreditUsdc;
    bool keeperCreditClaimableNow;
}

EngineStatusViewTypes

Git Source

Structs

ProtocolStatus

struct ProtocolStatus {
    uint8 phase;
    uint256 lastMarkPrice;
    uint64 lastMarkTime;
    bool oracleFrozen;
    bool fadWindow;
    uint256 fadMaxStaleness;
}

HousePoolEngineViewTypes

Git Source

Structs

HousePoolInputSnapshot

struct HousePoolInputSnapshot {
    uint256 physicalAssetsUsdc;
    uint256 netPhysicalAssetsUsdc;
    uint256 maxLiabilityUsdc;
    uint256 supplementalReservedUsdc;
    uint256 unrealizedMtmLiabilityUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 deferredKeeperCreditUsdc;
    uint256 protocolFeesUsdc;
    bool markFreshnessRequired;
    uint256 maxMarkStaleness;
}

HousePoolStatusSnapshot

struct HousePoolStatusSnapshot {
    uint64 lastMarkTime;
    bool oracleFrozen;
    bool degradedMode;
}

ICfdEngine

Git Source

Stateful CFD trading engine: processes orders and liquidates positions.

This remains a rich internal/admin integration interface. Product-facing consumers should prefer the slim public surfaces in IPerpsTraderActions, IPerpsTraderViews, IPerpsLPActions, IPerpsLPViews, IPerpsKeeper, IProtocolViews, and IMarginAccount. Live protocol contracts should prefer smaller role-specific interfaces like ICfdEngineCore.

Functions

clearinghouse

Margin clearinghouse address used for account margin locking/unlocking

function clearinghouse() external view returns (address);

orderRouter

Current order router allowed to execute orders through the engine.

function orderRouter() external view returns (address);

USDC

Settlement token used for fees, margin, and payouts

function USDC() external view returns (IERC20);

lastMarkPrice

Last mark price observed by the engine (8 decimals)

function lastMarkPrice() external view returns (uint256);

processOrderTyped

Router-facing order execution entrypoint with typed business-rule failures.

Reverts with CfdEngine__TypedOrderFailure for expected order invalidations so the router can apply deterministic failed-order bounty policy without selector matching.

function processOrderTyped(
    CfdTypes.Order memory order,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external;

recordDeferredKeeperCredit

Records deferred keeper credit when immediate clearinghouse settlement is unavailable.

Deferred keeper value is always later claimed as clearinghouse credit.

function recordDeferredKeeperCredit(
    address keeper,
    uint256 amountUsdc
) external;

reserveCloseOrderExecutionBounty

Reserves close-order execution bounty from free settlement first, then active position margin.

function reserveCloseOrderExecutionBounty(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 amountUsdc,
    address recipient
) external;

absorbRouterCancellationFee

Pulls router-custodied cancellation fees into protocol revenue.

function absorbRouterCancellationFee(
    uint256 amountUsdc
) external;

recordRouterProtocolFee

Books router-delivered protocol-owned inflow as accumulated fees after the router has already paid the vault.

function recordRouterProtocolFee(
    uint256 amountUsdc
) external;

creditKeeperExecutionBounty

Credits a keeper execution bounty into the beneficiary’s clearinghouse account.

Realizes carry first when the beneficiary account currently has an open position so the settlement-balance credit cannot retroactively dilute carry owed over the elapsed interval.

function creditKeeperExecutionBounty(
    address beneficiary,
    uint256 amountUsdc,
    uint256 price,
    uint64 publishTime
) external;

liquidatePosition

Liquidates an undercollateralized position, returns keeper bounty in USDC

function liquidatePosition(
    bytes32 accountId,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external returns (uint256 keeperBountyUsdc);

Parameters

NameTypeDescription
accountIdbytes32Account holding the position to liquidate
currentOraclePriceuint256Mark price from the oracle (8 decimals)
vaultDepthUsdcuint256Available vault liquidity (6 decimals)
publishTimeuint64Oracle publish timestamp

Returns

NameTypeDescription
keeperBountyUsdcuint256Bounty paid to the liquidation keeper (6 decimals)

realizeCarryBeforeMarginChange

Realizes accrued carry against the current reachable collateral before a user-level settlement balance mutation changes the carry basis.

function realizeCarryBeforeMarginChange(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) external;

previewLiquidation

Canonical liquidation preview using the vault’s current accounted depth.

function previewLiquidation(
    bytes32 accountId,
    uint256 oraclePrice
) external view returns (LiquidationPreview memory preview);

simulateLiquidation

Hypothetical liquidation simulation at a caller-supplied vault depth.

function simulateLiquidation(
    bytes32 accountId,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) external view returns (LiquidationPreview memory preview);

accumulatedFeesUsdc

Accumulated execution fees awaiting withdrawal (6 decimals)

function accumulatedFeesUsdc() external view returns (uint256);

totalDeferredTraderCreditUsdc

Deferred trader credit still owed to beneficiaries.

function totalDeferredTraderCreditUsdc() external view returns (uint256);

totalDeferredKeeperCreditUsdc

Deferred keeper credit still owed after failed immediate settlement.

function totalDeferredKeeperCreditUsdc() external view returns (uint256);

lastMarkTime

Timestamp of the last mark price update

function lastMarkTime() external view returns (uint64);

updateMarkPrice

Pushes a fresh mark price without processing an order.

This updates the cached mark only; carry is realized on execution and margin-mutating paths.

function updateMarkPrice(
    uint256 price,
    uint64 publishTime
) external;

Parameters

NameTypeDescription
priceuint256New mark price (8 decimals)
publishTimeuint64Oracle publish timestamp for the price update

CAP_PRICE

Protocol cap price (8 decimals). Oracle prices are clamped to this.

function CAP_PRICE() external view returns (uint256);

isFadWindow

True during weekend FX closure or admin-configured FAD days

function isFadWindow() external view returns (bool);

fadMaxStaleness

Maximum oracle staleness allowed during FAD windows

function fadMaxStaleness() external view returns (uint256);

isOracleFrozen

True only when FX markets are actually closed and oracle freshness can be relaxed.

function isOracleFrozen() external view returns (bool);

positions

Returns the current position tuple for an account.

function positions(
    bytes32 accountId
)
    external
    view
    returns (
        uint256 size,
        uint256 margin,
        uint256 entryPrice,
        uint256 maxProfitUsdc,
        CfdTypes.Side side,
        uint64 lastUpdateTime,
        int256 vpiAccrued
    );

getPositionLastCarryTimestamp

Returns the timestamp through which carry has been realized for the position.

function getPositionLastCarryTimestamp(
    bytes32 accountId
) external view returns (uint64);

degradedMode

True when the engine has latched degraded mode after a close revealed insolvency.

function degradedMode() external view returns (bool);

fadDayOverrides

Whether a given day number is an admin-configured FAD override

function fadDayOverrides(
    uint256 dayNumber
) external view returns (bool);

getProtocolStatus

function getProtocolStatus() external view returns (EngineStatusViewTypes.ProtocolStatus memory);

Errors

CfdEngine__TypedOrderFailure

error CfdEngine__TypedOrderFailure(
    CfdEnginePlanTypes.ExecutionFailurePolicyCategory failureCategory, uint8 failureCode, bool isClose
);

CfdEngine__MarkPriceOutOfOrder

error CfdEngine__MarkPriceOutOfOrder();

Structs

SideState

struct SideState {
    uint256 maxProfitUsdc;
    uint256 openInterest;
    uint256 entryNotional;
    uint256 totalMargin;
}

LiquidationPreview

struct LiquidationPreview {
    bool liquidatable;
    uint256 oraclePrice;
    int256 equityUsdc;
    int256 pnlUsdc;
    uint256 reachableCollateralUsdc;
    uint256 keeperBountyUsdc;
    uint256 seizedCollateralUsdc;
    uint256 settlementRetainedUsdc;
    uint256 freshTraderPayoutUsdc;
    uint256 existingDeferredConsumedUsdc;
    uint256 existingDeferredRemainingUsdc;
    uint256 immediatePayoutUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 badDebtUsdc;
    bool triggersDegradedMode;
    bool postOpDegradedMode;
    uint256 effectiveAssetsAfterUsdc;
    uint256 maxLiabilityAfterUsdc;
}

Enums

ProtocolPhase

High-level protocol lifecycle used by external status consumers. Active means the engine is wired and the vault has enabled live risk-taking.

enum ProtocolPhase {
    Configuring,
    Active,
    Degraded
}

ICfdEngineAccountLens

Git Source

Functions

getAccountCollateralView

Legacy detailed account lens kept for internal tooling, tests, and migration. Product-facing consumers should prefer IPerpsTraderViews via PerpsPublicLens.

function getAccountCollateralView(
    bytes32 accountId
) external view returns (CfdEngine.AccountCollateralView memory viewData);

getWithdrawableUsdc

function getWithdrawableUsdc(
    bytes32 accountId
) external view returns (uint256 withdrawableUsdc);

getAccountLedgerView

function getAccountLedgerView(
    bytes32 accountId
) external view returns (AccountLensViewTypes.AccountLedgerView memory viewData);

getAccountLedgerSnapshot

function getAccountLedgerSnapshot(
    bytes32 accountId
) external view returns (AccountLensViewTypes.AccountLedgerSnapshot memory snapshot);

ICfdEngineAdminHost

Git Source

Functions

applyRiskConfig

function applyRiskConfig(
    EngineRiskConfig calldata config
) external;

applyCalendarConfig

function applyCalendarConfig(
    EngineCalendarConfig calldata config
) external;

applyFreshnessConfig

function applyFreshnessConfig(
    EngineFreshnessConfig calldata config
) external;

Structs

EngineRiskConfig

struct EngineRiskConfig {
    CfdTypes.RiskParams riskParams;
    uint256 executionFeeBps;
}

EngineCalendarConfig

struct EngineCalendarConfig {
    uint256[] fadDayTimestamps;
    uint256 fadRunwaySeconds;
}

EngineFreshnessConfig

struct EngineFreshnessConfig {
    uint256 fadMaxStaleness;
    uint256 engineMarkStalenessLimit;
}

ICfdEngineCore

Git Source

Core/operator-facing engine surface used by live perps contracts.

Functions

clearinghouse

function clearinghouse() external view returns (address);

orderRouter

function orderRouter() external view returns (address);

settlementModule

function settlementModule() external view returns (address);

USDC

function USDC() external view returns (IERC20);

lastMarkPrice

function lastMarkPrice() external view returns (uint256);

riskParams

function riskParams()
    external
    view
    returns (
        uint256 vpiFactor,
        uint256 maxSkewRatio,
        uint256 maintMarginBps,
        uint256 initMarginBps,
        uint256 fadMarginBps,
        uint256 baseCarryBps,
        uint256 minBountyUsdc,
        uint256 bountyBps
    );

processOrderTyped

function processOrderTyped(
    CfdTypes.Order memory order,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external;

recordDeferredKeeperCredit

function recordDeferredKeeperCredit(
    address keeper,
    uint256 amountUsdc
) external;

reserveCloseOrderExecutionBounty

function reserveCloseOrderExecutionBounty(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 amountUsdc,
    address recipient
) external;

absorbRouterCancellationFee

function absorbRouterCancellationFee(
    uint256 amountUsdc
) external;

recordRouterProtocolFee

function recordRouterProtocolFee(
    uint256 amountUsdc
) external;

creditKeeperExecutionBounty

function creditKeeperExecutionBounty(
    address beneficiary,
    uint256 amountUsdc,
    uint256 price,
    uint64 publishTime
) external;

accumulatedFeesUsdc

function accumulatedFeesUsdc() external view returns (uint256);

totalDeferredTraderCreditUsdc

function totalDeferredTraderCreditUsdc() external view returns (uint256);

totalDeferredKeeperCreditUsdc

function totalDeferredKeeperCreditUsdc() external view returns (uint256);

liquidatePosition

function liquidatePosition(
    bytes32 accountId,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external returns (uint256 keeperBountyUsdc);

lastMarkTime

function lastMarkTime() external view returns (uint64);

updateMarkPrice

function updateMarkPrice(
    uint256 price,
    uint64 publishTime
) external;

CAP_PRICE

function CAP_PRICE() external view returns (uint256);

realizeCarryBeforeMarginChange

function realizeCarryBeforeMarginChange(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) external;

checkpointCarryUsingStoredMark

function checkpointCarryUsingStoredMark(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) external;

isFadWindow

function isFadWindow() external view returns (bool);

fadMaxStaleness

function fadMaxStaleness() external view returns (uint256);

engineMarkStalenessLimit

function engineMarkStalenessLimit() external view returns (uint256);

fadDayOverrides

function fadDayOverrides(
    uint256 dayNumber
) external view returns (bool);

isOracleFrozen

function isOracleFrozen() external view returns (bool);

positions

function positions(
    bytes32 accountId
)
    external
    view
    returns (
        uint256 size,
        uint256 margin,
        uint256 entryPrice,
        uint256 maxProfitUsdc,
        CfdTypes.Side side,
        uint64 lastUpdateTime,
        int256 vpiAccrued
    );

degradedMode

function degradedMode() external view returns (bool);

getProtocolStatus

function getProtocolStatus() external view returns (EngineStatusViewTypes.ProtocolStatus memory status);

Errors

CfdEngine__TypedOrderFailure

error CfdEngine__TypedOrderFailure(
    CfdEnginePlanTypes.ExecutionFailurePolicyCategory failureCategory, uint8 failureCode, bool isClose
);

CfdEngine__MarkPriceOutOfOrder

error CfdEngine__MarkPriceOutOfOrder();

ICfdEngineLens

Git Source

Functions

engine

function engine() external view returns (address);

previewClose

function previewClose(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 oraclePrice
) external view returns (CfdEngine.ClosePreview memory preview);

previewOpenRevertCode

function previewOpenRevertCode(
    bytes32 accountId,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 oraclePrice,
    uint64 publishTime
) external view returns (uint8 code);

previewOpenFailurePolicyCategory

function previewOpenFailurePolicyCategory(
    bytes32 accountId,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 oraclePrice,
    uint64 publishTime
) external view returns (CfdEnginePlanTypes.OpenFailurePolicyCategory category);

simulateClose

function simulateClose(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) external view returns (CfdEngine.ClosePreview memory preview);

previewLiquidation

function previewLiquidation(
    bytes32 accountId,
    uint256 oraclePrice
) external view returns (CfdEngine.LiquidationPreview memory preview);

simulateLiquidation

function simulateLiquidation(
    bytes32 accountId,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) external view returns (CfdEngine.LiquidationPreview memory preview);

ICfdEnginePlanner

Git Source

Functions

computeOpenMarginAfter

function computeOpenMarginAfter(
    uint256 marginAfterFunding,
    int256 netMarginChange
) external pure returns (bool drained, uint256 marginAfter);

planOpen

function planOpen(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.OpenDelta memory delta);

planClose

function planClose(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.CloseDelta memory delta);

planLiquidation

function planLiquidation(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.LiquidationDelta memory delta);

getOpenFailurePolicyCategory

function getOpenFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) external pure returns (CfdEnginePlanTypes.OpenFailurePolicyCategory);

getExecutionFailurePolicyCategory

function getExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) external pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

getCloseExecutionFailurePolicyCategory

function getCloseExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.CloseRevertCode code
) external pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

ICfdEngineProtocolLens

Git Source

Functions

getProtocolAccountingSnapshot

Legacy detailed protocol lens kept for internal tooling, tests, and migration. Product-facing consumers should prefer IPerpsTraderViews, IPerpsLPViews, and IProtocolViews via PerpsPublicLens.

function getProtocolAccountingSnapshot()
    external
    view
    returns (ProtocolLensViewTypes.ProtocolAccountingSnapshot memory snapshot);

getHousePoolInputSnapshot

function getHousePoolInputSnapshot(
    uint256 markStalenessLimit
) external view returns (HousePoolEngineViewTypes.HousePoolInputSnapshot memory snapshot);

getHousePoolStatusSnapshot

function getHousePoolStatusSnapshot()
    external
    view
    returns (HousePoolEngineViewTypes.HousePoolStatusSnapshot memory snapshot);

ICfdEngineSettlementHost

Git Source

Functions

clearinghouse

function clearinghouse() external view returns (address);

vault

function vault() external view returns (address);

orderRouter

function orderRouter() external view returns (address);

settlementApplyFundingAndMark

function settlementApplyFundingAndMark(
    uint256 newMarkPrice,
    uint64 newMarkTime
) external;

settlementSyncTotalSideMargin

function settlementSyncTotalSideMargin(
    CfdTypes.Side side,
    uint256 marginBefore,
    uint256 marginAfter
) external;

settlementApplySideDelta

function settlementApplySideDelta(
    CfdTypes.Side side,
    int256 maxProfitDelta,
    int256 openInterestDelta,
    int256 entryNotionalDelta
) external;

settlementConsumeDeferredTraderPayout

function settlementConsumeDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) external;

settlementRecordDeferredTraderPayout

function settlementRecordDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) external;

settlementAccumulateFees

function settlementAccumulateFees(
    uint256 amountUsdc
) external;

settlementAccumulateBadDebt

function settlementAccumulateBadDebt(
    uint256 amountUsdc
) external;

settlementWritePosition

function settlementWritePosition(
    bytes32 accountId,
    CfdEngineSettlementTypes.PositionState calldata position
) external;

settlementDeletePosition

function settlementDeletePosition(
    bytes32 accountId
) external;

ICfdEngineSettlementModule

Git Source

Functions

executeOpen

function executeOpen(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.OpenDelta calldata delta,
    CfdTypes.Position calldata currentPosition,
    uint64 publishTime
) external;

executeClose

function executeClose(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.CloseDelta calldata delta,
    CfdTypes.Position calldata currentPosition,
    uint64 publishTime
) external;

executeLiquidation

function executeLiquidation(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.LiquidationDelta calldata delta,
    uint64 publishTime
) external returns (uint256 keeperBountyUsdc);

ICfdVault

Git Source

Vault that custodies USDC backing the CFD trading system.

Functions

totalAssets

Canonical economic USDC backing recognized by the vault (6 decimals). Ignores unsolicited positive token transfers until explicitly accounted, but still reflects raw-balance shortfalls if assets leave the vault unexpectedly.

function totalAssets() external view returns (uint256);

payOut

Transfers USDC from the vault to a recipient

function payOut(
    address recipient,
    uint256 amount
) external;

Parameters

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

recordProtocolInflow

Increases canonical vault assets to recognize a legitimate protocol-owned inflow.

This is the controlled accounting path for endogenous protocol gains that should increase economic vault depth. It does not require raw excess to be present and may also be used to restore canonical accounting after a raw-balance shortfall has already reduced totalAssets() via the min(rawBalance, accountedAssets) boundary. Reverts if the caller is unauthorized.

function recordProtocolInflow(
    uint256 amount
) external;

recordClaimantInflow

Records claimant-owned value that should ultimately flow through the tranche waterfall.

CashArrived increments canonical accounted assets because raw USDC arrived in this flow. AlreadyRetained only routes ownership for value already retained physically by the vault.

function recordClaimantInflow(
    uint256 amount,
    ClaimantInflowKind kind,
    ClaimantInflowCashMode cashMode
) external;

markStalenessLimit

Maximum age for mark price freshness checks outside FAD mode (seconds)

function markStalenessLimit() external view returns (uint256);

isSeedLifecycleComplete

Returns true once both tranche seed positions exist.

function isSeedLifecycleComplete() external view returns (bool);

hasSeedLifecycleStarted

Returns true if bootstrap seeding has started for either tranche.

function hasSeedLifecycleStarted() external view returns (bool);

canAcceptOrdinaryDeposits

Returns true once ordinary LP deposits are allowed.

function canAcceptOrdinaryDeposits() external view returns (bool);

canIncreaseRisk

Returns true once risk-increasing trader actions are allowed.

function canIncreaseRisk() external view returns (bool);

isTradingActive

Returns true if owner has activated trading after seed completion.

function isTradingActive() external view returns (bool);

Enums

ClaimantInflowKind

enum ClaimantInflowKind {
    Revenue,
    Recapitalization
}

ClaimantInflowCashMode

enum ClaimantInflowCashMode {
    CashArrived,
    AlreadyRetained
}

IHousePool

Git Source

Two-tranche USDC pool that acts as counterparty to CFD traders. Senior tranche earns fixed yield; junior absorbs first-loss and excess profit.

Functions

seniorPrincipal

Total USDC attributed to the senior tranche (6 decimals)

function seniorPrincipal() external view returns (uint256);

juniorPrincipal

Total USDC attributed to the junior tranche (6 decimals)

function juniorPrincipal() external view returns (uint256);

seniorHighWaterMark

Senior high-water mark used to block dilutive recapitalizing deposits.

function seniorHighWaterMark() external view returns (uint256);

unassignedAssets

Accounted LP assets currently quarantined pending explicit bootstrap / assignment (6 decimals)

function unassignedAssets() external view returns (uint256);

depositSenior

function depositSenior(
    uint256 amount
) external;

withdrawSenior

function withdrawSenior(
    uint256 amount,
    address receiver
) external;

depositJunior

function depositJunior(
    uint256 amount
) external;

withdrawJunior

function withdrawJunior(
    uint256 amount,
    address receiver
) external;

assignUnassignedAssets

Explicitly bootstraps quarantined LP assets into a tranche and mints matching shares.

function assignUnassignedAssets(
    bool toSenior,
    address receiver
) external;

initializeSeedPosition

Seeds a tranche with permanent share-backed minimum ownership using real USDC.

Canonical deployment should initialize both tranche seeds before enabling ordinary LP lifecycle.

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

getMaxSeniorWithdraw

Max withdrawable by senior, capped by free USDC

function getMaxSeniorWithdraw() external view returns (uint256);

getMaxJuniorWithdraw

Max withdrawable by junior, subordinated behind senior

function getMaxJuniorWithdraw() external view returns (uint256);

getPendingTrancheState

Read-only tranche state as if reconcile() ran immediately with current inputs.

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

Returns

NameTypeDescription
seniorPrincipalUsdcuint256Simulated senior principal after reconcile (6 decimals)
juniorPrincipalUsdcuint256Simulated junior principal after reconcile (6 decimals)
maxSeniorWithdrawUsdcuint256Simulated senior withdrawal cap after reconcile (6 decimals)
maxJuniorWithdrawUsdcuint256Simulated junior withdrawal cap after reconcile (6 decimals)

reconcile

Settles revenue/loss waterfall between tranches

function reconcile() external;

isWithdrawalLive

Whether withdrawals are currently possible (not degraded, mark is fresh)

function isWithdrawalLive() external view returns (bool);

hasSeedLifecycleStarted

function hasSeedLifecycleStarted() external view returns (bool);

canAcceptOrdinaryDeposits

function canAcceptOrdinaryDeposits() external view returns (bool);

canAcceptTrancheDeposits

function canAcceptTrancheDeposits(
    bool isSenior
) external view returns (bool);

canIncreaseRisk

function canIncreaseRisk() external view returns (bool);

isTradingActive

function isTradingActive() external view returns (bool);

isOracleFrozen

function isOracleFrozen() external view returns (bool);

frozenLpFeeBps

function frozenLpFeeBps(
    bool isSenior
) external view returns (uint256);

IMarginAccount

Git Source

Public trader-facing margin account surface stripped of internal reservation and bucket plumbing.

Functions

depositMargin

function depositMargin(
    uint256 amount
) external;

withdrawMargin

function withdrawMargin(
    uint256 amount
) external;

getAccountEquityUsdc

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

getFreeBuyingPowerUsdc

Returns settlement equity that is not currently locked into margin buckets.

This is a clearinghouse-local view and does not account for engine withdrawal guards.

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

IMarginClearinghouse

Git Source

USDC-only cross-margin account system that holds settlement balances and settles PnL for CFD positions.

This is the full operator/integration surface. Product-facing consumers should prefer IMarginAccount and avoid depending on reservation buckets, internal custody buckets, or settlement-path helpers.

Functions

balanceUsdc

Returns the settlement USDC balance for an account.

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

lockedMarginUsdc

Returns the locked USDC margin for an account

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

getLockedMarginBuckets

Returns the typed locked-margin buckets for an account.

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

getOrderReservation

Returns the reservation record for a specific order id.

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

getAccountReservationSummary

Returns the aggregate active reservation summary for an account.

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

lockPositionMargin

Locks trader-owned settlement into the active position margin bucket.

function lockPositionMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external;

unlockPositionMargin

Unlocks active position margin back into free settlement.

function unlockPositionMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external;

lockCommittedOrderMargin

Locks trader-owned settlement into the committed-order bucket reserved for queued open orders.

function lockCommittedOrderMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external;

reserveCommittedOrderMargin

Reserves committed-order margin for a specific order id inside the clearinghouse reservation ledger.

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

unlockCommittedOrderMargin

Unlocks committed-order margin back into free settlement when a queued open order is released.

function unlockCommittedOrderMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external;

releaseOrderReservation

Releases any remaining reservation balance for an order back into free settlement.

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

releaseOrderReservationIfActive

Releases any remaining reservation balance for an order if it is still active.

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

consumeOrderReservation

Consumes a specific amount from an order reservation, capped by its remaining balance.

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

consumeAccountOrderReservations

Consumes active order reservations for an account in FIFO reservation order.

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

consumeOrderReservationsById

Consumes the supplied active order reservations in FIFO order until the requested amount is exhausted.

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

lockReservedSettlement

Locks settlement into a reserved bucket excluded from generic order/position margin release paths.

function lockReservedSettlement(
    bytes32 accountId,
    uint256 amountUsdc
) external;

unlockReservedSettlement

Unlocks settlement from the reserved bucket back into free settlement.

function unlockReservedSettlement(
    bytes32 accountId,
    uint256 amountUsdc
) external;

settleUsdc

Adjusts settlement USDC for realized PnL, deferred-claim servicing, or rebates (+credit, -debit).

function settleUsdc(
    bytes32 accountId,
    int256 amount
) external;

creditSettlementAndLockMargin

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

function creditSettlementAndLockMargin(
    bytes32 accountId,
    uint256 amountUsdc
) external;

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 returns (int256 netMarginChangeUsdc);

consumeSettlementLoss

Consumes a realized settlement loss from free settlement plus the active position margin bucket.

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

consumeCloseLoss

Consumes close-path losses from settlement buckets while preserving the remaining live position margin and reserved escrow.

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

applyLiquidationSettlementPlan

Applies a pre-planned liquidation settlement mutation while preserving reserved escrow.

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

seizeUsdc

Transfers settlement USDC from an account to a recipient (losses, fees, or bad debt)

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

reserveCloseExecutionBountyFromSettlement

Reserves free-settlement USDC for a close-order execution bounty with carry checkpointing.

Restricted to the engine’s atomic fresh close-bounty path.

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

reserveStaleCloseExecutionBountyFromSettlement

Reserves free-settlement USDC for a stale close-order execution bounty without checkpointing carry.

Restricted to the engine’s atomic stale close-bounty path.

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

seizePositionMarginUsdc

Transfers settlement USDC from active position margin to a recipient and unlocks the same amount.

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

reserveStaleCloseExecutionBountyFromPositionMargin

Reserves active position margin for a stale close-order execution bounty without checkpointing carry.

Restricted to the engine’s bounded stale close-bounty path.

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

getAccountUsdcBuckets

function getAccountUsdcBuckets(
    bytes32 accountId
) external view returns (AccountUsdcBuckets memory buckets);

getAccountEquityUsdc

Returns total account equity in settlement USDC (6 decimals)

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

getFreeBuyingPowerUsdc

Returns strictly free buying power after subtracting locked margin (6 decimals)

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

Structs

LockedMarginBuckets

struct LockedMarginBuckets {
    // Canonical custody bucket backing currently live positions.
    uint256 positionMarginUsdc;
    uint256 committedOrderMarginUsdc;
    uint256 reservedSettlementUsdc;
    uint256 totalLockedMarginUsdc;
}

OrderReservation

struct OrderReservation {
    bytes32 accountId;
    ReservationBucket bucket;
    ReservationStatus status;
    uint96 originalAmountUsdc;
    uint96 remainingAmountUsdc;
}

AccountReservationSummary

struct AccountReservationSummary {
    uint256 activeCommittedOrderMarginUsdc;
    uint256 activeReservationCount;
}

AccountUsdcBuckets

struct AccountUsdcBuckets {
    uint256 settlementBalanceUsdc;
    uint256 totalLockedMarginUsdc;
    uint256 activePositionMarginUsdc;
    uint256 otherLockedMarginUsdc;
    uint256 freeSettlementUsdc;
}

LiquidationSettlementPlan

struct LiquidationSettlementPlan {
    uint256 settlementRetainedUsdc;
    uint256 settlementSeizedUsdc;
    uint256 freshTraderPayoutUsdc;
    uint256 badDebtUsdc;
    uint256 positionMarginUnlockedUsdc;
    uint256 otherLockedMarginUnlockedUsdc;
}

Enums

MarginBucket

enum MarginBucket {
    Position,
    CommittedOrder,
    ReservedSettlement
}

ReservationBucket

enum ReservationBucket {
    CommittedOrder
}

ReservationStatus

enum ReservationStatus {
    None,
    Active,
    Consumed,
    Released
}

IOrderRouterAccounting

Git Source

Shared accounting-facing subset of OrderRouter used by engine views and margin bookkeeping.

This remains an internal/admin integration surface. Product-facing consumers should prefer IPerpsTraderViews via PerpsPublicLens and avoid depending on queue-accounting internals directly.

Functions

syncMarginQueue

Prunes any zero-remaining committed-order reservations out of the router’s margin queue for an account.

function syncMarginQueue(
    bytes32 accountId
) external;

getAccountEscrow

Returns aggregate queued escrow attributed to an account across all pending orders.

function getAccountEscrow(
    bytes32 accountId
) external view returns (AccountEscrowView memory escrow);

accountHeadOrderId

Returns the current account-queue head id for pending-order traversal.

function accountHeadOrderId(
    bytes32 accountId
) external view returns (uint64 headOrderId);

getPendingOrderView

Returns the pending-order view for a specific order plus the next account-queue order id.

function getPendingOrderView(
    uint64 orderId
) external view returns (PendingOrderView memory pending, uint64 nextAccountOrderId);

pendingOrderCounts

Returns the number of pending orders currently attributed to an account.

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

getMarginReservationIds

Returns the current router-maintained margin-queue order ids for an account in FIFO order.

This is a structural traversal helper; committed-margin value remains owned by the clearinghouse reservation ledger.

function getMarginReservationIds(
    bytes32 accountId
) external view returns (uint64[] memory orderIds);

Structs

AccountEscrowView

Router/accounting view of queued order escrow attributed to an account.

committedMarginUsdc is derived from canonical MarginClearinghouse reservation state. executionBountyUsdc is router-custodied bounty escrow reserved for queued orders.

struct AccountEscrowView {
    uint256 committedMarginUsdc;
    uint256 executionBountyUsdc;
    uint256 pendingOrderCount;
}

PendingOrderView

struct PendingOrderView {
    uint64 orderId;
    bool isClose;
    CfdTypes.Side side;
    uint256 sizeDelta;
    uint256 marginDelta;
    uint256 targetPrice;
    uint64 commitTime;
    uint64 commitBlock;
    uint256 committedMarginUsdc;
    uint256 executionBountyUsdc;
}

Enums

OrderStatus

enum OrderStatus {
    None,
    Pending,
    Executed,
    Failed
}

IOrderRouterAdminHost

Git Source

Functions

applyRouterConfig

function applyRouterConfig(
    RouterConfig calldata config
) external;

applyOracleConfig

function applyOracleConfig(
    OracleConfig calldata config
) external;

Structs

RouterConfig

struct RouterConfig {
    uint256 maxOrderAge;
    uint256 orderExecutionStalenessLimit;
    uint256 liquidationStalenessLimit;
    uint256 pythMaxConfidenceRatioBps;
    uint256 minOpenNotionalUsdc;
    uint256 openOrderExecutionBountyBps;
    uint256 minOpenOrderExecutionBountyUsdc;
    uint256 maxOpenOrderExecutionBountyUsdc;
    uint256 closeOrderExecutionBountyUsdc;
    uint256 maxPendingOrders;
    uint256 minEngineGas;
    uint256 maxPruneOrdersPerCall;
}

OracleConfig

struct OracleConfig {
    address pyth;
    bytes32[] feedIds;
    uint256[] quantities;
    uint256[] basePrices;
    bool[] inversions;
}

IPerpsAdmin

Git Source

Administrative surface for perps configuration, emergency controls, and one-time setup.

Functions

setPauser

function setPauser(
    address newPauser
) external;

pause

function pause() external;

unpause

function unpause() external;

IPerpsKeeper

Git Source

Keeper-facing execution and liquidation surface for the simplified product API.

Functions

executeOrder

Executes the next eligible delayed order using fresh oracle data.

function executeOrder(
    uint64 orderId,
    bytes[] calldata pythUpdateData
) external payable;

executeOrderBatch

Executes a bounded batch of eligible delayed orders using a shared oracle update.

function executeOrderBatch(
    uint64 maxOrderId,
    bytes[] calldata pythUpdateData
) external payable;

executeLiquidation

Liquidates an unsafe account using fresh oracle data.

function executeLiquidation(
    bytes32 accountId,
    bytes[] calldata pythUpdateData
) external payable;

IPerpsLP

Git Source

Inherits: IPerpsLPActions, IPerpsLPViews

Combined LP-facing surface for the simplified perps product API.

IPerpsLPActions

Git Source

LP-facing senior/junior tranche action surface.

Functions

depositSenior

function depositSenior(
    uint256 amount
) external;

withdrawSenior

function withdrawSenior(
    uint256 amount,
    address receiver
) external;

depositJunior

function depositJunior(
    uint256 amount
) external;

withdrawJunior

function withdrawJunior(
    uint256 amount,
    address receiver
) external;

IPerpsLPViews

Git Source

Compact LP-facing read surface for senior and junior tranches.

Functions

getSeniorTranche

function getSeniorTranche() external view returns (PerpsViewTypes.TrancheView memory viewData);

getJuniorTranche

function getJuniorTranche() external view returns (PerpsViewTypes.TrancheView memory viewData);

getLpStatus

function getLpStatus() external view returns (PerpsViewTypes.LpStatusView memory viewData);

IPerpsTrader

Git Source

Inherits: IPerpsTraderActions, IPerpsTraderViews

Combined trader-facing surface for the simplified perps product API.

IPerpsTraderActions

Git Source

Trader-facing action surface aligned with the current delayed-order router model.

Functions

commitOrder

function commitOrder(
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 targetPrice,
    bool isClose
) external;

IPerpsTraderViews

Git Source

Compact trader-facing read surface for the simplified perps product API.

Functions

getTraderAccount

function getTraderAccount(
    bytes32 accountId
) external view returns (PerpsViewTypes.TraderAccountView memory viewData);

getPosition

function getPosition(
    bytes32 accountId
) external view returns (PerpsViewTypes.PositionView memory viewData);

getPendingOrders

function getPendingOrders(
    bytes32 accountId
) external view returns (PerpsViewTypes.PendingOrderView[] memory pending);

isLiquidatable

function isLiquidatable(
    bytes32 accountId
) external view returns (bool);

IProtocolViews

Git Source

Compact protocol-wide read surface for product consumers.

Functions

getProtocolStatus

function getProtocolStatus() external view returns (PerpsViewTypes.ProtocolStatusView memory viewData);

ITrancheVaultBootstrap

Git Source

Functions

previewDeposit

function previewDeposit(
    uint256 assets
) external view returns (uint256 shares);

bootstrapMint

function bootstrapMint(
    uint256 shares,
    address receiver
) external;

configureSeedPosition

function configureSeedPosition(
    address receiver,
    uint256 floorShares
) external;

IWithdrawGuard

Git Source

Pre-withdrawal hook that prevents clearinghouse withdrawals while positions are open.

Functions

checkWithdraw

Reverts if the account is not allowed to withdraw from the clearinghouse. Implementations may inspect current clearinghouse balances after tentative debit.

function checkWithdraw(
    bytes32 accountId
) external;

Parameters

NameTypeDescription
accountIdbytes32Cross-margin account to check

PerpsViewTypes

Git Source

Canonical public-facing view structs for the simplified perps product surface.

Structs

TraderAccountView

struct TraderAccountView {
    uint256 equityUsdc;
    uint256 withdrawableUsdc;
    uint256 pendingOrderMarginUsdc;
    uint256 pendingExecutionBountyUsdc;
    bool hasOpenPosition;
    bool liquidatable;
}

PositionView

struct PositionView {
    bool exists;
    CfdTypes.Side side;
    uint256 size;
    uint256 entryPrice;
    uint256 marginUsdc;
    int256 unrealizedPnlUsdc;
    uint256 maintenanceMarginUsdc;
    bool liquidatable;
}

PendingOrderView

struct PendingOrderView {
    uint64 orderId;
    CfdTypes.Side side;
    uint256 sizeDelta;
    int256 marginDeltaUsdc;
    uint256 acceptablePrice;
    bool isReduceOnly;
    OrderStatus status;
}

TrancheView

struct TrancheView {
    uint256 totalAssetsUsdc;
    uint256 totalShares;
    uint256 sharePrice;
    uint256 maxWithdrawUsdc;
    uint256 frozenLpFeeBps;
    bool depositEnabled;
    bool withdrawEnabled;
    bool oracleFrozen;
}

LpStatusView

struct LpStatusView {
    bool tradingActive;
    bool withdrawalLive;
    uint64 lastMarkTime;
    bool oracleFresh;
    bool oracleFrozen;
}

ProtocolStatusView

struct ProtocolStatusView {
    uint8 phase;
    uint256 lastMarkPrice;
    uint64 lastMarkTime;
    bool oracleFrozen;
    bool fadWindow;
    bool tradingActive;
    bool withdrawalLive;
}

Enums

OrderStatus

enum OrderStatus {
    None,
    Pending,
    Executed,
    Failed
}

ProtocolLensViewTypes

Git Source

Structs

ProtocolAccountingSnapshot

struct ProtocolAccountingSnapshot {
    uint256 vaultAssetsUsdc;
    uint256 netPhysicalAssetsUsdc;
    uint256 maxLiabilityUsdc;
    uint256 effectiveSolvencyAssetsUsdc;
    uint256 withdrawalReservedUsdc;
    uint256 freeUsdc;
    uint256 accumulatedFeesUsdc;
    uint256 accumulatedBadDebtUsdc;
    uint256 totalDeferredTraderCreditUsdc;
    uint256 totalDeferredKeeperCreditUsdc;
    bool degradedMode;
    bool hasLiveLiability;
}

Contents

CashPriorityLib

Git Source

Functions

reserveFreshPayouts

function reserveFreshPayouts(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) internal pure returns (SeniorCashReservation memory reservation);

reserveDeferredClaim

function reserveDeferredClaim(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc,
    uint256 deferredClaimAmountUsdc
) internal pure returns (SeniorCashReservation memory reservation);

reservedSeniorCashUsdc

function reservedSeniorCashUsdc(
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) internal pure returns (uint256);

availableCashForFreshPayouts

function availableCashForFreshPayouts(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) internal pure returns (uint256);

availableCashForDeferredBeneficiaryClaim

function availableCashForDeferredBeneficiaryClaim(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc,
    uint256 claimAmountUsdc
) internal pure returns (uint256);

availableCashForProtocolFeeWithdrawal

function availableCashForProtocolFeeWithdrawal(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) internal pure returns (uint256);

canPayFreshPayout

function canPayFreshPayout(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc,
    uint256 amountUsdc
) internal pure returns (bool);

canPayDeferredBeneficiaryClaim

function canPayDeferredBeneficiaryClaim(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc,
    uint256 claimAmountUsdc
) internal pure returns (bool);

canWithdrawProtocolFees

function canWithdrawProtocolFees(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc,
    uint256 amountUsdc
) internal pure returns (bool);

_saturatingSub

function _saturatingSub(
    uint256 lhs,
    uint256 rhs
) private pure returns (uint256);

_buildSeniorCashReservation

function _buildSeniorCashReservation(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) private pure returns (SeniorCashReservation memory reservation);

Structs

SeniorCashReservation

struct SeniorCashReservation {
    uint256 physicalAssetsUsdc;
    uint256 protocolFeesUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 deferredKeeperCreditUsdc;
    uint256 totalSeniorClaimsUsdc;
    uint256 reservedSeniorCashUsdc;
    uint256 protocolFeeWithdrawalUsdc;
    uint256 freeCashUsdc;
    uint256 deferredClaimServiceableUsdc;
}

CfdEnginePlanLib

Git Source

Title: CfdEnginePlanLib

Pure plan functions for the CfdEngine plan→apply architecture. Each function takes a RawSnapshot and returns a typed delta describing all effects. No storage reads, no external calls — purely deterministic over memory inputs.

Functions

_liquidationVpiClawbackUsdc

function _liquidationVpiClawbackUsdc(
    int256 vpiAccrued
) private pure returns (uint256);

computeOpenMarginAfter

function computeOpenMarginAfter(
    uint256 marginAfterFunding,
    int256 netMarginChange
) internal pure returns (bool drained, uint256 marginAfter);

computeSideTotalMarginAfterOpen

function computeSideTotalMarginAfterOpen(
    uint256 sideTotalMarginAfterFunding,
    uint256 effectivePositionMarginAfterFunding,
    uint256 positionMarginAfterOpen
) internal pure returns (uint256 sideTotalMarginAfterOpen);

getOpenFailurePolicyCategory

function getOpenFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) internal pure returns (CfdEnginePlanTypes.OpenFailurePolicyCategory);

getExecutionFailurePolicyCategory

function getExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) internal pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

getExecutionFailurePolicyCategory

function getExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.CloseRevertCode code
) internal pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

_selectedAndOpposite

function _selectedAndOpposite(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Side side
)
    private
    pure
    returns (CfdEnginePlanTypes.SideSnapshot memory selected, CfdEnginePlanTypes.SideSnapshot memory opposite);

_absSkewUsdc

function _absSkewUsdc(
    CfdEnginePlanTypes.SideSnapshot memory bull,
    CfdEnginePlanTypes.SideSnapshot memory bear,
    uint256 price
) private pure returns (uint256);

_postOpenSkewUsdc

function _postOpenSkewUsdc(
    CfdEnginePlanTypes.SideSnapshot memory bull,
    CfdEnginePlanTypes.SideSnapshot memory bear,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 price
) private pure returns (uint256);

_planDeferredTraderCreditConsumption

function _planDeferredTraderCreditConsumption(
    uint256 deferredTraderCreditUsdc,
    uint256 shortfallUsdc,
    bool shortfallAlreadyIncludesDeferred
) private pure returns (uint256 consumedUsdc, uint256 remainingUsdc, uint256 badDebtUsdc);

_planCloseDeferredTraderCreditConsumption

function _planCloseDeferredTraderCreditConsumption(
    uint256 deferredTraderCreditUsdc,
    CfdEngineSettlementLib.CloseSettlementResult memory lossResult
)
    private
    pure
    returns (uint256 consumedUsdc, uint256 remainingUsdc, uint256 feeRecoveredUsdc, uint256 badDebtUsdc);

planOpen

function planOpen(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) internal pure returns (CfdEnginePlanTypes.OpenDelta memory delta);

_applyPendingCarryRealizationToOpenSnapshot

function _applyPendingCarryRealizationToOpenSnapshot(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    uint256 pendingCarryUsdc
) private pure returns (bool hasShortfall);

_buildPostOpenRiskState

function _buildPostOpenRiskState(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdEnginePlanTypes.OpenDelta memory delta
) private pure returns (PositionRiskAccountingLib.PositionRiskState memory riskState);

_isOpenInsolventAfterPlan

function _isOpenInsolventAfterPlan(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Side side,
    CfdEnginePlanTypes.OpenDelta memory delta,
    CfdEnginePlanTypes.SideSnapshot memory bull,
    CfdEnginePlanTypes.SideSnapshot memory bear
) private pure returns (bool);

planClose

function planClose(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) internal pure returns (CfdEnginePlanTypes.CloseDelta memory delta);

_computeCloseSolvency

function _computeCloseSolvency(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdEnginePlanTypes.CloseDelta memory delta,
    CfdEnginePlanTypes.SideSnapshot memory bull,
    CfdEnginePlanTypes.SideSnapshot memory bear
) private pure returns (CfdEnginePlanTypes.SolvencyPreview memory sp);

_buildCloseSettlementBuckets

function _buildCloseSettlementBuckets(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    uint256 marginToFreeUsdc,
    bool includeOtherLockedMargin
) private pure returns (IMarginClearinghouse.AccountUsdcBuckets memory);

planLiquidation

function planLiquidation(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    uint256 executionPrice,
    uint64 publishTime
) internal pure returns (CfdEnginePlanTypes.LiquidationDelta memory delta);

CfdEngineSettlementLib

Git Source

Functions

collectSettlementDeficit

function collectSettlementDeficit(
    uint256 availableUsdc,
    uint256 owedUsdc
) internal pure returns (DebtCollectionResult memory result);

closeSettlementResult

function closeSettlementResult(
    uint256 availableUsdc,
    uint256 owedUsdc,
    uint256 execFeeUsdc
) internal pure returns (CloseSettlementResult memory result);

closeSettlementResultForTerminalBuckets

function closeSettlementResultForTerminalBuckets(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    uint256 protectedLockedMarginUsdc,
    uint256 owedUsdc,
    uint256 execFeeUsdc
) internal pure returns (CloseSettlementResult memory result);

liquidationSettlementResult

function liquidationSettlementResult(
    uint256 accountBalanceUsdc,
    int256 residualUsdc
) internal pure returns (LiquidationSettlementResult memory result);

Structs

DebtCollectionResult

struct DebtCollectionResult {
    uint256 seizedUsdc;
    uint256 shortfallUsdc;
}

CloseSettlementResult

struct CloseSettlementResult {
    uint256 seizedUsdc;
    uint256 shortfallUsdc;
    uint256 collectedExecFeeUsdc;
    uint256 badDebtUsdc;
}

LiquidationSettlementResult

struct LiquidationSettlementResult {
    uint256 targetBalanceUsdc;
    uint256 seizedUsdc;
    uint256 payoutUsdc;
    uint256 badDebtUsdc;
}

CfdEngineSnapshotsLib

Git Source

Structs

SolvencySnapshot

struct SolvencySnapshot {
    uint256 physicalAssets;
    uint256 protocolFees;
    uint256 netPhysicalAssets;
    uint256 maxLiability;
    uint256 effectiveSolvencyAssets;
}

CloseAccountingLib

Git Source

Functions

buildCloseState

function buildCloseState(
    uint256 positionSize,
    uint256 positionMarginUsdc,
    uint256 entryPrice,
    uint256 maxProfitUsdc,
    int256 vpiAccrued,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 oraclePrice,
    uint256 capPrice,
    uint256 preSkewUsdc,
    uint256 postSkewUsdc,
    uint256 vaultDepthUsdc,
    uint256 vpiFactor,
    uint256 executionFeeBps
) internal pure returns (CloseState memory state);

Structs

CloseState

struct CloseState {
    int256 realizedPnlUsdc;
    uint256 marginToFreeUsdc;
    uint256 remainingMarginUsdc;
    uint256 remainingSize;
    uint256 maxProfitReductionUsdc;
    int256 proportionalAccrualUsdc;
    int256 vpiDeltaUsdc;
    uint256 executionFeeUsdc;
    int256 netSettlementUsdc;
}

HousePoolAccountingLib

Git Source

Functions

buildWithdrawalSnapshot

function buildWithdrawalSnapshot(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory engineSnapshot
) internal pure returns (WithdrawalSnapshot memory snapshot);

buildReconcileSnapshot

function buildReconcileSnapshot(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory engineSnapshot
) internal pure returns (ReconcileSnapshot memory snapshot);

getMarkFreshnessPolicy

function getMarkFreshnessPolicy(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot
) internal pure returns (MarkFreshnessPolicy memory policy);

isMarkFresh

function isMarkFresh(
    uint64 lastMarkTime,
    uint256 limit,
    uint256 currentTimestamp
) internal pure returns (bool);

Structs

WithdrawalSnapshot

struct WithdrawalSnapshot {
    uint256 physicalAssets;
    uint256 maxLiability;
    uint256 protocolFees;
    uint256 reserved;
    uint256 freeUsdc;
}

ReconcileSnapshot

struct ReconcileSnapshot {
    uint256 physicalAssets;
    uint256 protocolFees;
    uint256 deferredLiabilities;
    uint256 cashMinusFees;
    uint256 mtm;
    uint256 distributable;
}

MarkFreshnessPolicy

struct MarkFreshnessPolicy {
    bool required;
    uint256 maxStaleness;
}

HousePoolFreshnessLib

Git Source

Functions

markIsFreshForReconcile

function markIsFreshForReconcile(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot,
    uint256 currentTimestamp
) internal pure returns (bool);

withdrawalsLive

function withdrawalsLive(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot,
    uint256 currentTimestamp
) internal pure returns (bool);

markFresh

function markFresh(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot,
    uint256 currentTimestamp
) internal pure returns (bool);

HousePoolPendingLivePlanLib

Git Source

Functions

planApplyPendingClaimantBuckets

function planApplyPendingClaimantBuckets(
    HousePoolPendingPreviewLib.PendingAccountingState memory state,
    uint256 currentSeniorPrincipal,
    HousePoolPendingPreviewLib.ClaimantPendingBuckets memory claimantBuckets
) internal pure returns (PendingLivePlan memory plan);

Structs

PendingLivePlan

struct PendingLivePlan {
    HousePoolPendingPreviewLib.PendingAccountingState state;
    bool seniorPrincipalChanged;
}

HousePoolPendingPreviewLib

Git Source

Functions

applyPendingClaimantBucketsPreview

function applyPendingClaimantBucketsPreview(
    PendingAccountingState memory state,
    ClaimantPendingBuckets memory claimantBuckets
) internal pure;

applyClaimantRecapitalizationIntent

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

applyRevenueIntent

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

Structs

ClaimantPendingBuckets

struct ClaimantPendingBuckets {
    uint256 recapitalizationUsdc;
    uint256 revenueUsdc;
}

PendingAccountingState

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

HousePoolReconcilePlanLib

Git Source

Functions

planReconcile

function planReconcile(
    HousePoolPendingPreviewLib.PendingAccountingState memory state,
    HousePoolAccountingLib.ReconcileSnapshot memory snapshot,
    uint256 pendingBucketAssets,
    uint256 seniorRateBps,
    uint256 yieldElapsed,
    bool markFresh
) internal pure returns (ReconcilePlan memory plan);

juniorRevenueWithoutOwners

function juniorRevenueWithoutOwners(
    ReconcilePlan memory plan
) internal pure returns (uint256);

Structs

ReconcilePlan

struct ReconcilePlan {
    HousePoolPendingPreviewLib.PendingAccountingState state;
    uint256 yieldAccrued;
    bool markFresh;
    bool juniorSupplyZero;
    bool claimedEquityZero;
    bool revenue;
    uint256 deltaUsdc;
    uint256 juniorPrincipalBeforeRevenue;
}

HousePoolSeedLifecycleLib

Git Source

Functions

isSeedLifecycleComplete

function isSeedLifecycleComplete(
    bool seniorSeedInitialized,
    bool juniorSeedInitialized
) internal pure returns (bool);

hasSeedLifecycleStarted

function hasSeedLifecycleStarted(
    bool seniorSeedInitialized,
    bool juniorSeedInitialized
) internal pure returns (bool);

canAcceptOrdinaryDeposits

function canAcceptOrdinaryDeposits(
    bool seniorSeedInitialized,
    bool juniorSeedInitialized,
    bool isTradingActive
) internal pure returns (bool);

canIncreaseRisk

function canIncreaseRisk(
    bool seniorSeedInitialized,
    bool juniorSeedInitialized,
    bool isTradingActive
) internal pure returns (bool);

tradingActivationReady

function tradingActivationReady(
    bool seniorSeedInitialized,
    bool juniorSeedInitialized
) internal pure returns (bool);

hasPendingBootstrap

function hasPendingBootstrap(
    uint256 unassignedAssets
) internal pure returns (bool);

HousePoolTrancheGateLib

Git Source

Functions

trancheDepositsAllowed

function trancheDepositsAllowed(
    bool ordinaryDepositsAllowed,
    bool paused,
    uint256 unassignedAssets,
    bool markFreshForReconcile,
    uint256 projectedUnassignedAssets,
    bool isSenior,
    uint256 projectedSeniorPrincipal,
    uint256 projectedSeniorHighWaterMark
) internal pure returns (bool);

HousePoolWaterfallAccountingLib

Git Source

Constants

BPS

uint256 internal constant BPS = 10_000;

SECONDS_PER_YEAR

uint256 internal constant SECONDS_PER_YEAR = 31_536_000;

Functions

accrueSeniorYield

function accrueSeniorYield(
    uint256 seniorPrincipal,
    uint256 seniorRateBps,
    uint256 elapsed
) internal pure returns (uint256);

planReconcile

function planReconcile(
    uint256 seniorPrincipal,
    uint256 juniorPrincipal,
    uint256 distributableUsdc,
    uint256 seniorRateBps,
    uint256 elapsed
) internal pure returns (ReconcilePlan memory plan);

scaleSeniorOnWithdraw

function scaleSeniorOnWithdraw(
    WaterfallState memory state,
    uint256 withdrawAmountUsdc
) internal pure returns (WaterfallState memory nextState);

distributeRevenue

function distributeRevenue(
    WaterfallState memory state,
    uint256 revenueUsdc
) internal pure returns (WaterfallState memory nextState);

absorbLoss

function absorbLoss(
    WaterfallState memory state,
    uint256 lossUsdc
) internal pure returns (WaterfallState memory nextState);

Structs

WaterfallState

struct WaterfallState {
    uint256 seniorPrincipal;
    uint256 juniorPrincipal;
    uint256 unpaidSeniorYield;
    uint256 seniorHighWaterMark;
}

ReconcilePlan

struct ReconcilePlan {
    uint256 yieldAccrued;
    bool isRevenue;
    uint256 deltaUsdc;
}

HousePoolWithdrawalPreviewLib

Git Source

Functions

reserveAssets

function reserveAssets(
    HousePoolAccountingLib.WithdrawalSnapshot memory snapshot,
    uint256 reservedAssets
) internal pure returns (HousePoolAccountingLib.WithdrawalSnapshot memory nextSnapshot);

seniorWithdrawCap

function seniorWithdrawCap(
    uint256 freeUsdc,
    uint256 seniorPrincipal
) internal pure returns (uint256);

juniorWithdrawCap

function juniorWithdrawCap(
    uint256 freeUsdc,
    uint256 seniorPrincipal,
    uint256 juniorPrincipal
) internal pure returns (uint256);

LiquidationAccountingLib

Git Source

Functions

buildLiquidationState

function buildLiquidationState(
    uint256 size,
    uint256 oraclePrice,
    uint256 reachableCollateralUsdc,
    int256 equityUsdc,
    uint256 maintMarginBps,
    uint256 minBountyUsdc,
    uint256 bountyBps,
    uint256 tokenScale
) internal pure returns (LiquidationState memory state);

settlementForState

function settlementForState(
    LiquidationState memory state
) internal pure returns (CfdEngineSettlementLib.LiquidationSettlementResult memory result);

Structs

LiquidationState

struct LiquidationState {
    int256 equityUsdc;
    uint256 reachableCollateralUsdc;
    uint256 maintenanceMarginUsdc;
    uint256 keeperBountyUsdc;
}

MarginClearinghouseAccountingLib

Git Source

Functions

buildAccountUsdcBuckets

function buildAccountUsdcBuckets(
    uint256 settlementBalanceUsdc,
    uint256 positionMarginUsdc,
    uint256 committedOrderMarginUsdc,
    uint256 reservedSettlementUsdc
) internal pure returns (IMarginClearinghouse.AccountUsdcBuckets memory buckets);

buildPartialCloseUsdcBuckets

function buildPartialCloseUsdcBuckets(
    uint256 settlementBalanceUsdc,
    uint256 positionMarginUsdc,
    uint256 committedOrderMarginUsdc,
    uint256 reservedSettlementUsdc
) internal pure returns (IMarginClearinghouse.AccountUsdcBuckets memory buckets);

getSettlementBalanceUsdc

function getSettlementBalanceUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256);

getFreeSettlementUsdc

function getFreeSettlementUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256);

getPositionMarginUsdc

function getPositionMarginUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256);

getQueuedReservedUsdc

function getQueuedReservedUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256);

getGenericReachableUsdc

function getGenericReachableUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256 reachableUsdc);

planFundingLossConsumption

function planFundingLossConsumption(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    uint256 lossUsdc
) internal pure returns (SettlementConsumption memory consumption);

planOpenCostApplication

function planOpenCostApplication(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    uint256 marginDeltaUsdc,
    int256 tradeCostUsdc
) internal pure returns (OpenCostPlan memory plan);

getTerminalReachableUsdc

function getTerminalReachableUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets
) internal pure returns (uint256 reachableUsdc);

getSettlementReachableUsdc

function getSettlementReachableUsdc(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    uint256 protectedLockedMarginUsdc
) internal pure returns (uint256 reachableUsdc);

planTerminalLossConsumption

function planTerminalLossConsumption(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    uint256 protectedLockedMarginUsdc,
    uint256 lossUsdc
) internal pure returns (SettlementConsumption memory consumption);

applyFundingLossMutation

function applyFundingLossMutation(
    IMarginClearinghouse.AccountUsdcBuckets memory,
    SettlementConsumption memory consumption
) internal pure returns (BucketMutation memory mutation);

applyTerminalLossMutation

function applyTerminalLossMutation(
    IMarginClearinghouse.AccountUsdcBuckets memory,
    uint256,
    SettlementConsumption memory consumption
) internal pure returns (BucketMutation memory mutation);

planLiquidationResidual

function planLiquidationResidual(
    IMarginClearinghouse.AccountUsdcBuckets memory buckets,
    int256 residualUsdc
) internal pure returns (LiquidationResidualPlan memory plan);

Structs

SettlementConsumption

struct SettlementConsumption {
    uint256 freeSettlementConsumedUsdc;
    uint256 activeMarginConsumedUsdc;
    uint256 otherLockedMarginConsumedUsdc;
    uint256 totalConsumedUsdc;
    uint256 uncoveredUsdc;
}

BucketMutation

struct BucketMutation {
    uint256 settlementDebitUsdc;
    uint256 positionMarginUnlockedUsdc;
    uint256 otherLockedMarginUnlockedUsdc;
}

OpenCostPlan

struct OpenCostPlan {
    int256 netMarginChangeUsdc;
    uint256 settlementCreditUsdc;
    uint256 settlementDebitUsdc;
    uint256 positionMarginUnlockedUsdc;
    uint256 positionMarginLockedUsdc;
    uint256 resultingSettlementBalanceUsdc;
    uint256 resultingPositionMarginUsdc;
    uint256 resultingFreeSettlementUsdc;
    bool insufficientFreeEquity;
    bool insufficientPositionMargin;
}

LiquidationResidualPlan

struct LiquidationResidualPlan {
    uint256 settlementRetainedUsdc;
    uint256 settlementSeizedUsdc;
    uint256 freshTraderPayoutUsdc;
    uint256 badDebtUsdc;
    BucketMutation mutation;
}

MarketCalendarLib

Git Source

Constants

SECONDS_PER_DAY

uint256 internal constant SECONDS_PER_DAY = 86_400;

SECONDS_PER_HOUR

uint256 internal constant SECONDS_PER_HOUR = 3600;

Functions

isFadWindow

function isFadWindow(
    uint256 timestamp,
    bool todayOverride,
    bool tomorrowOverride,
    uint256 fadRunwaySeconds
) internal pure returns (bool);

isOracleFrozen

function isOracleFrozen(
    uint256 timestamp,
    bool todayOverride
) internal pure returns (bool);

_dayAndHour

function _dayAndHour(
    uint256 timestamp
) private pure returns (uint256 dayOfWeek, uint256 hourOfDay);

OpenAccountingLib

Git Source

Functions

buildOpenState

function buildOpenState(
    OpenInputs memory inputs
) internal pure returns (OpenState memory state);

effectiveMarginAfterTradeCost

function effectiveMarginAfterTradeCost(
    uint256 marginUsdc,
    int256 tradeCostUsdc
) internal pure returns (uint256 effectiveMarginUsdc);

Structs

OpenInputs

struct OpenInputs {
    uint256 currentSize;
    uint256 currentEntryPrice;
    CfdTypes.Side side;
    uint256 sizeDelta;
    uint256 price;
    uint256 capPrice;
    uint256 preSkewUsdc;
    uint256 postSkewUsdc;
    uint256 vaultDepthUsdc;
    uint256 executionFeeBps;
    CfdTypes.RiskParams riskParams;
}

OpenState

struct OpenState {
    uint256 addedMaxProfitUsdc;
    uint256 oldEntryNotional;
    uint256 newEntryPrice;
    uint256 newSize;
    uint256 newEntryNotional;
    uint256 postSkewUsdc;
    int256 vpiUsdc;
    uint256 notionalUsdc;
    uint256 executionFeeUsdc;
    int256 tradeCostUsdc;
    uint256 maintenanceMarginUsdc;
    uint256 initialMarginRequirementUsdc;
}

OracleFreshnessPolicyLib

Git Source

Functions

getPolicy

function getPolicy(
    Mode mode,
    bool oracleFrozen,
    bool isFad,
    uint256 engineMarkStalenessLimit,
    uint256 poolMarkStalenessLimit,
    uint256 routerOrderExecutionStalenessLimit,
    uint256 routerLiquidationStalenessLimit,
    uint256 fadMaxStaleness
) internal pure returns (Policy memory policy);

isStale

function isStale(
    uint256 oraclePublishTime,
    uint256 maxStaleness,
    uint256 currentTimestamp
) internal pure returns (bool);

_effectiveLiveMarkLimit

function _effectiveLiveMarkLimit(
    uint256 engineMarkStalenessLimit,
    uint256 poolMarkStalenessLimit
) private pure returns (uint256);

Structs

Policy

struct Policy {
    bool closeOnly;
    bool requireStoredMark;
    bool allowAnyStoredMark;
    uint256 maxStaleness;
}

Enums

Mode

enum Mode {
    OpenExecution,
    CloseExecution,
    Liquidation,
    PoolReconcile,
    CloseCommitFallback,
    MarkRefresh
}

OrderFailurePolicyLib

Git Source

Functions

isPredictablyInvalidOpen

function isPredictablyInvalidOpen(
    CfdEnginePlanTypes.OpenFailurePolicyCategory category
) internal pure returns (bool);

OrderOraclePolicyLib

Git Source

Functions

getOracleExecutionPolicy

function getOracleExecutionPolicy(
    OracleAction action,
    bool oracleFrozen,
    bool isFad,
    uint256 liveExecutionStaleness,
    uint256 liveLiquidationStaleness,
    uint256 fadMaxStaleness
) internal pure returns (OracleExecutionPolicy memory policy);

isStale

function isStale(
    uint256 oraclePublishTime,
    uint256 maxStaleness,
    uint256 currentTimestamp
) internal pure returns (bool);

Structs

OracleExecutionPolicy

struct OracleExecutionPolicy {
    bool closeOnly;
    uint256 maxStaleness;
}

Enums

OracleAction

enum OracleAction {
    OrderExecution,
    MarkRefresh,
    Liquidation
}

PositionRiskAccountingLib

Git Source

Functions

_vpiClawbackUsdc

function _vpiClawbackUsdc(
    int256 vpiAccrued
) private pure returns (uint256);

computeLpBackedNotionalUsdc

function computeLpBackedNotionalUsdc(
    uint256 size,
    uint256 price,
    uint256 reachableCollateralUsdc
) internal pure returns (uint256 lpBackedNotionalUsdc);

computePendingCarryUsdc

function computePendingCarryUsdc(
    uint256 lpBackedNotionalUsdc,
    uint256 baseCarryBps,
    uint256 timeDelta
) internal pure returns (uint256 carryUsdc);

buildPositionRiskState

function buildPositionRiskState(
    CfdTypes.Position memory pos,
    uint256 price,
    uint256 capPrice,
    uint256 reachableCollateralUsdc,
    uint256 requiredBps
) internal pure returns (PositionRiskState memory state);

buildPositionRiskStateWithCarry

function buildPositionRiskStateWithCarry(
    CfdTypes.Position memory pos,
    uint256 price,
    uint256 capPrice,
    uint256 pendingCarryUsdc,
    uint256 reachableCollateralUsdc,
    uint256 requiredBps
) internal pure returns (PositionRiskState memory state);

Structs

PositionRiskState

struct PositionRiskState {
    int256 unrealizedPnlUsdc;
    int256 equityUsdc;
    uint256 currentNotionalUsdc;
    uint256 maintenanceMarginUsdc;
    bool liquidatable;
}

SolvencyAccountingLib

Git Source

Functions

getMaxLiability

function getMaxLiability(
    uint256 bullMaxProfitUsdc,
    uint256 bearMaxProfitUsdc
) internal pure returns (uint256);

getMaxLiabilityAfterClose

function getMaxLiabilityAfterClose(
    uint256 bullMaxProfitUsdc,
    uint256 bearMaxProfitUsdc,
    CfdTypes.Side side,
    uint256 maxProfitReductionUsdc
) internal pure returns (uint256);

buildSolvencyState

function buildSolvencyState(
    uint256 physicalAssetsUsdc,
    uint256 protocolFeesUsdc,
    uint256 maxLiabilityUsdc,
    uint256 deferredTraderCreditUsdc,
    uint256 deferredKeeperCreditUsdc
) internal pure returns (SolvencyState memory state);

effectiveAssetsAfterPendingPayout

function effectiveAssetsAfterPendingPayout(
    SolvencyState memory state,
    uint256 pendingVaultPayoutUsdc
) internal pure returns (uint256);

isInsolvent

function isInsolvent(
    SolvencyState memory state
) internal pure returns (bool);

previewPostOpSolvency

function previewPostOpSolvency(
    SolvencyState memory currentState,
    PreviewDelta memory delta,
    bool alreadyDegraded
) internal pure returns (PreviewResult memory result);

_applySignedDelta

function _applySignedDelta(
    uint256 value,
    int256 delta
) private pure returns (uint256 updatedValue);

Structs

PreviewDelta

struct PreviewDelta {
    int256 physicalAssetsDeltaUsdc;
    uint256 protocolFeesDeltaUsdc;
    uint256 maxLiabilityAfterUsdc;
    int256 deferredTraderPayoutDeltaUsdc;
    int256 deferredKeeperCreditDeltaUsdc;
    uint256 pendingVaultPayoutUsdc;
}

PreviewResult

struct PreviewResult {
    uint256 effectiveAssetsAfterUsdc;
    uint256 maxLiabilityAfterUsdc;
    bool triggersDegradedMode;
    bool postOpDegradedMode;
}

SolvencyState

struct SolvencyState {
    uint256 physicalAssetsUsdc;
    uint256 protocolFeesUsdc;
    uint256 netPhysicalAssetsUsdc;
    uint256 maxLiabilityUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 deferredKeeperCreditUsdc;
    uint256 withdrawalReservedUsdc;
    uint256 freeWithdrawableUsdc;
    uint256 effectiveAssetsUsdc;
}

Contents

OrderEscrowAccounting

Git Source

Inherits: IOrderRouterAccounting

Constants

engine

ICfdEngineCore public immutable engine;

clearinghouse

IMarginClearinghouse internal immutable clearinghouse;

USDC

IERC20 internal immutable USDC;

State Variables

orderRecords

mapping(uint64 => OrderRecord) internal orderRecords;

pendingOrderCounts

mapping(bytes32 => uint256) public pendingOrderCounts;

pendingCloseSize

mapping(bytes32 => uint256) public pendingCloseSize;

accountHeadOrderId

mapping(bytes32 => uint64) public accountHeadOrderId;

accountTailOrderId

mapping(bytes32 => uint64) internal accountTailOrderId;

marginHeadOrderId

mapping(bytes32 => uint64) public marginHeadOrderId;

marginTailOrderId

mapping(bytes32 => uint64) public marginTailOrderId;

Functions

constructor

constructor(
    address _engine
);

getAccountEscrow

function getAccountEscrow(
    bytes32 accountId
) public view override returns (IOrderRouterAccounting.AccountEscrowView memory escrow);

_summarizePendingOrders

function _summarizePendingOrders(
    bytes32 accountId
)
    internal
    view
    returns (
        uint256 pendingOrderCount,
        uint256 executionBountyUsdc,
        uint256 pendingCloseSize_,
        bool hasTerminalCloseQueued
    );

_nextCommitId

function _nextCommitId() internal view virtual returns (uint64);

getMarginReservationIds

function getMarginReservationIds(
    bytes32 accountId
) public view override returns (uint64[] memory orderIds);

_reserveExecutionBounty

function _reserveExecutionBounty(
    bytes32 accountId,
    uint64 orderId,
    uint256 sizeDelta,
    uint256 executionBountyUsdc,
    bool isClose
) internal;

_reserveCommittedMargin

function _reserveCommittedMargin(
    bytes32 accountId,
    uint64 orderId,
    bool isClose,
    uint256 marginDelta
) internal;

_consumeOrderEscrow

function _consumeOrderEscrow(
    uint64 orderId,
    bool success,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal returns (uint256 executionBountyUsdc);

_collectExecutionBounty

function _collectExecutionBounty(
    uint64 orderId,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal returns (uint256 executionBountyUsdc);

_releaseCommittedMargin

function _releaseCommittedMargin(
    uint64 orderId
) internal;

_linkMarginOrder

function _linkMarginOrder(
    bytes32 accountId,
    uint64 orderId
) internal;

_linkAccountOrder

function _linkAccountOrder(
    bytes32 accountId,
    uint64 orderId
) internal;

_unlinkAccountOrder

function _unlinkAccountOrder(
    bytes32 accountId,
    uint64 orderId
) internal;

_unlinkMarginOrder

function _unlinkMarginOrder(
    bytes32 accountId,
    uint64 orderId
) internal;

_pruneMarginQueue

function _pruneMarginQueue(
    bytes32 accountId
) internal;

_orderRecord

function _orderRecord(
    uint64 orderId
) internal view virtual returns (OrderRecord storage record);

_reserveCloseExecutionBounty

function _reserveCloseExecutionBounty(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 executionBountyUsdc
) internal virtual;

_revertInsufficientFreeEquity

function _revertInsufficientFreeEquity() internal pure virtual;

_revertMarginOrderLinkCorrupted

function _revertMarginOrderLinkCorrupted() internal pure virtual;

_revertPendingOrderLinkCorrupted

function _revertPendingOrderLinkCorrupted() internal pure virtual;

Structs

OrderRecord

struct OrderRecord {
    CfdTypes.Order core;
    IOrderRouterAccounting.OrderStatus status;
    uint256 executionBountyUsdc;
    uint64 nextGlobalOrderId;
    uint64 prevGlobalOrderId;
    uint64 nextAccountOrderId;
    uint64 prevAccountOrderId;
    uint64 nextMarginOrderId;
    uint64 prevMarginOrderId;
    bool inAccountQueue;
    bool inMarginQueue;
}

OrderExecutionOrchestrator

Git Source

Inherits: OrderOracleExecution, OrderQueueBook

Constants

PANIC_SELECTOR

bytes4 internal constant PANIC_SELECTOR = 0x4e487b71;

TYPED_ORDER_FAILURE_SELECTOR

bytes4 internal constant TYPED_ORDER_FAILURE_SELECTOR = ICfdEngineCore.CfdEngine__TypedOrderFailure.selector;

MARK_PRICE_OUT_OF_ORDER_SELECTOR

bytes4 internal constant MARK_PRICE_OUT_OF_ORDER_SELECTOR = ICfdEngineCore.CfdEngine__MarkPriceOutOfOrder.selector;

State Variables

minEngineGas

uint256 public minEngineGas;

maxPruneOrdersPerCall

uint256 public maxPruneOrdersPerCall;

Functions

_maxOrderAge

function _maxOrderAge() internal view virtual returns (uint256);

_queueHeadOrderId

function _queueHeadOrderId() internal view virtual override returns (uint64);

_setQueueHeadOrderId

function _setQueueHeadOrderId(
    uint64 orderId
) internal virtual override;

_revertNoOrdersToExecute

function _revertNoOrdersToExecute() internal pure virtual;

_revertInsufficientGas

function _revertInsufficientGas() internal pure virtual;

_revertMevDetected

function _revertMevDetected() internal pure virtual;

_revertCloseOnlyMode

function _revertCloseOnlyMode() internal pure virtual;

_releaseCommittedMarginForExecution

function _releaseCommittedMarginForExecution(
    uint64 orderId
) internal virtual;

_deleteOrder

function _deleteOrder(
    uint64 orderId,
    IOrderRouterAccounting.OrderStatus terminalStatus
) internal virtual;

_skipStaleOrders

function _skipStaleOrders(
    uint64 upToId,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal returns (uint256 skipped);

_pruneExpiredHeadOrders

function _pruneExpiredHeadOrders(
    uint64 upToId,
    uint256 maxPrunes,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal returns (uint256 pruned);

_processTypedOrderExecution

function _processTypedOrderExecution(
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint256 vaultDepth,
    uint64 oraclePublishTime
) internal returns (bool success, OrderFailReason failureReason, FailedOrderOutcome failureOutcome);

_executePendingOrder

function _executePendingOrder(
    uint64 orderId,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 oraclePublishTime,
    RouterExecutionContext memory executionContext,
    bool revertOnBlockedExecution,
    uint256 pythFee
) internal returns (OrderExecutionStepResult result);

_finalizeOrCleanupOrder

function _finalizeOrCleanupOrder(
    uint64 orderId,
    uint256 pythFee,
    bool success,
    FailedOrderOutcome failedOutcome,
    bool refundEthNow,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal;

_decodeTypedOrderFailure

function _decodeTypedOrderFailure(
    bytes memory revertData
)
    internal
    pure
    returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory failureCategory, uint8 failureCode, bool isClose);

_failedOutcomeFromEngineRevert

function _failedOutcomeFromEngineRevert(
    CfdTypes.Order memory order,
    bytes memory revertData
) internal pure returns (FailedOrderOutcome outcome);

_failedOutcomeForTerminalFailure

function _failedOutcomeForTerminalFailure(
    CfdTypes.Order memory order
) internal pure returns (FailedOrderOutcome outcome);

_failedOutcomeForSlippageFailure

function _failedOutcomeForSlippageFailure(
    CfdTypes.Order memory order
) internal pure returns (FailedOrderOutcome outcome);

_cleanupOrder

function _cleanupOrder(
    uint64 orderId,
    FailedOrderOutcome,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal returns (uint256 executionBountyUsdc);

_finalizeExecution

function _finalizeExecution(
    uint64 orderId,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal;

_sendEth

function _sendEth(
    address to,
    uint256 amount
) internal virtual;

Events

OrderExecuted

event OrderExecuted(uint64 indexed orderId, uint256 executionPrice);

OrderFailed

event OrderFailed(uint64 indexed orderId, OrderFailReason reason);

Enums

OrderExecutionStepResult

enum OrderExecutionStepResult {
    Continue,
    Break,
    Return
}

FailedOrderOutcome

enum FailedOrderOutcome {
    ClearerFull
}

OrderFailReason

enum OrderFailReason {
    Expired,
    CloseOnly,
    SlippageExceeded,
    EnginePanic,
    AccountLiquidated,
    EngineRevert
}

OrderOracleExecution

Git Source

Inherits: OrderEscrowAccounting

Constants

vault

ICfdVault internal immutable vault;

engineLens

ICfdEngineLens internal immutable engineLens;

State Variables

pyth

IPyth public pyth;

pythFeedIds

bytes32[] public pythFeedIds;

quantities

uint256[] public quantities;

basePrices

uint256[] public basePrices;

inversions

bool[] public inversions;

orderExecutionStalenessLimit

uint256 public orderExecutionStalenessLimit = 60;

liquidationStalenessLimit

uint256 public liquidationStalenessLimit = 15;

pythMaxConfidenceRatioBps

uint256 public pythMaxConfidenceRatioBps = 10_000;

Functions

_revertZeroAddress

function _revertZeroAddress() internal pure virtual;

_revertEmptyFeeds

function _revertEmptyFeeds() internal pure virtual;

_revertLengthMismatch

function _revertLengthMismatch() internal pure virtual;

_revertInvalidBasePrice

function _revertInvalidBasePrice() internal pure virtual;

_revertInvalidWeights

function _revertInvalidWeights() internal pure virtual;

_revertMissingPythUpdateData

function _revertMissingPythUpdateData() internal pure virtual;

_revertInsufficientPythFee

function _revertInsufficientPythFee() internal pure virtual;

_revertMockModeDisabled

function _revertMockModeDisabled() internal pure virtual;

_revertOraclePriceTooStale

function _revertOraclePriceTooStale() internal pure virtual;

_revertOracleConfidenceTooWide

function _revertOracleConfidenceTooWide() internal pure virtual;

_revertOraclePublishTimeOutOfOrder

function _revertOraclePublishTimeOutOfOrder() internal pure virtual;

_revertMevOraclePriceTooStale

function _revertMevOraclePriceTooStale() internal pure virtual;

_revertOraclePriceNegative

function _revertOraclePriceNegative() internal pure virtual;

constructor

constructor(
    address _engine,
    address _engineLens,
    address _vault,
    address _pyth,
    bytes32[] memory _feedIds,
    uint256[] memory _quantities,
    uint256[] memory _basePrices,
    bool[] memory _inversions
) OrderEscrowAccounting(_engine);

_currentRouterExecutionContext

function _currentRouterExecutionContext() internal view returns (RouterExecutionContext memory context);

_prepareOrderExecutionOracle

function _prepareOrderExecutionOracle(
    bytes[] calldata pythUpdateData,
    uint256 mockFallbackPrice
) internal returns (OracleUpdateResult memory update, RouterExecutionContext memory executionContext);

_prepareMarkRefreshOracle

function _prepareMarkRefreshOracle(
    bytes[] calldata pythUpdateData
) internal returns (OracleUpdateResult memory update);

_prepareLiquidationOracle

function _prepareLiquidationOracle(
    bytes[] calldata pythUpdateData
) internal returns (OracleUpdateResult memory update);

_executionPolicyForOrder

function _executionPolicyForOrder(
    bool isClose,
    bool oracleFrozen,
    bool isFadWindow
) internal view returns (OracleFreshnessPolicyLib.Policy memory);

_resolveOraclePrice

function _resolveOraclePrice(
    bytes[] calldata pythUpdateData,
    uint256 mockFallbackPrice,
    uint256 maxStaleness,
    uint256 maxPublishTimeDivergence
) internal returns (uint256 price, uint64 publishTime, uint256 pythFee);

_setOracleConfig

function _setOracleConfig(
    address newPyth,
    bytes32[] memory newFeedIds,
    uint256[] memory newQuantities,
    uint256[] memory newBasePrices,
    bool[] memory newInversions
) internal;

_validateOracleConfig

function _validateOracleConfig(
    address newPyth,
    bytes32[] memory newFeedIds,
    uint256[] memory newQuantities,
    uint256[] memory newBasePrices,
    bool[] memory newInversions
) internal pure;

_computeBasketPrice

function _computeBasketPrice(
    uint256 maxStaleness,
    uint256 maxPublishTimeDivergence
) internal view returns (uint256 basketPrice, uint256 minPublishTime);

_checkSlippage

function _checkSlippage(
    CfdTypes.Order memory order,
    uint256 executionPrice
) internal pure returns (bool);

_commitReferencePrice

function _commitReferencePrice() internal view returns (uint256 price);

_canUseCommitMarkForOpenPrefilter

function _canUseCommitMarkForOpenPrefilter() internal view returns (bool);

_isOracleFrozen

function _isOracleFrozen() internal view returns (bool);

_isCloseOnlyWindow

function _isCloseOnlyWindow() internal view returns (bool);

_invertPythPrice

function _invertPythPrice(
    int64 price,
    int32 expo
) internal pure returns (uint256);

_normalizePythPrice

function _normalizePythPrice(
    int64 price,
    int32 expo
) internal pure returns (uint256);

Structs

RouterExecutionContext

struct RouterExecutionContext {
    bool oracleFrozen;
    bool isFadWindow;
    OracleFreshnessPolicyLib.Policy policy;
}

OracleUpdateResult

struct OracleUpdateResult {
    uint256 executionPrice;
    uint64 oraclePublishTime;
    uint256 pythFee;
}

OrderQueueBook

Git Source

Inherits: OrderEscrowAccounting

Functions

_queueHeadOrderId

function _queueHeadOrderId() internal view virtual returns (uint64);

_setQueueHeadOrderId

function _setQueueHeadOrderId(
    uint64 orderId
) internal virtual;

_queueTailOrderId

function _queueTailOrderId() internal view virtual returns (uint64);

_setQueueTailOrderId

function _setQueueTailOrderId(
    uint64 orderId
) internal virtual;

_revertOrderNotPending

function _revertOrderNotPending() internal pure virtual;

_linkGlobalOrder

function _linkGlobalOrder(
    uint64 orderId
) internal;

_unlinkGlobalOrder

function _unlinkGlobalOrder(
    uint64 orderId
) internal;

_pendingOrder

function _pendingOrder(
    uint64 orderId
) internal view returns (OrderRecord storage record, CfdTypes.Order memory order);

_getQueuedPositionView

function _getQueuedPositionView(
    bytes32 accountId
) internal view returns (QueuedPositionView memory queuedPosition);

Structs

QueuedPositionView

struct QueuedPositionView {
    bool exists;
    CfdTypes.Side side;
    uint256 size;
}

CfdEngine

Git Source

Inherits: IWithdrawGuard, ICfdEngineAdminHost, Ownable2Step, ReentrancyGuardTransient

Title: CfdEngine

The core mathematical ledger for Plether CFDs.

Settles all funds through the MarginClearinghouse and CfdVault.

Note: security-contact: contact@plether.com

Constants

CAP_PRICE

uint256 public immutable CAP_PRICE;

USDC

IERC20 public immutable USDC;

clearinghouse

IMarginClearinghouse public immutable clearinghouse;

State Variables

vault

ICfdVault public vault;

planner

ICfdEnginePlanner public planner;

settlementModule

ICfdEngineSettlementModule public settlementModule;

admin

address public admin;

sides

SideState[2] public sides;

lastMarkPrice

uint256 public lastMarkPrice;

lastMarkTime

uint64 public lastMarkTime;

accumulatedFeesUsdc

uint256 public accumulatedFeesUsdc;

accumulatedBadDebtUsdc

uint256 public accumulatedBadDebtUsdc;

unsettledCarryUsdc

mapping(bytes32 => uint256) public unsettledCarryUsdc;

degradedMode

bool public degradedMode;

riskParams

CfdTypes.RiskParams public riskParams;

_positions

mapping(bytes32 => StoredPosition) internal _positions;

deferredTraderCreditUsdc

mapping(bytes32 => uint256) public deferredTraderCreditUsdc;

totalDeferredTraderCreditUsdc

uint256 public totalDeferredTraderCreditUsdc;

deferredKeeperCreditUsdc

mapping(address => uint256) public deferredKeeperCreditUsdc;

totalDeferredKeeperCreditUsdc

uint256 public totalDeferredKeeperCreditUsdc;

orderRouter

address public orderRouter;

fadDayOverrides

mapping(uint256 => bool) public fadDayOverrides;

_fadOverrideDays

uint256[] private _fadOverrideDays;

fadMaxStaleness

uint256 public fadMaxStaleness = 3 days;

fadRunwaySeconds

uint256 public fadRunwaySeconds = 3 hours;

engineMarkStalenessLimit

uint256 public engineMarkStalenessLimit = 60;

executionFeeBps

uint256 public executionFeeBps = 4;

Functions

_sideIndex

function _sideIndex(
    CfdTypes.Side side
) internal pure returns (uint256);

_sideState

function _sideState(
    CfdTypes.Side side
) internal view returns (SideState storage state);

_oppositeSide

function _oppositeSide(
    CfdTypes.Side side
) internal pure returns (CfdTypes.Side);

_sideAndOppositeStates

function _sideAndOppositeStates(
    CfdTypes.Side side
) internal view returns (SideState storage selected, SideState storage opposite);

_bullAndBearStates

function _bullAndBearStates() internal view returns (SideState storage bullState, SideState storage bearState);

_checkpointDeferredClaimCarryIfPossible

function _checkpointDeferredClaimCarryIfPossible(
    bytes32 accountId,
    StoredPosition storage pos
) internal;

_claimDeferredBalance

function _claimDeferredBalance(
    uint256 amount,
    bytes32 accountId
) internal returns (uint256 claimAmountUsdc);

_increaseDeferredLiability

function _increaseDeferredLiability(
    uint256 currentAmountUsdc,
    uint256 currentTotalUsdc,
    uint256 amountUsdc
) internal pure returns (uint256 updatedAmountUsdc, uint256 updatedTotalUsdc);

_decreaseDeferredLiability

function _decreaseDeferredLiability(
    uint256 currentAmountUsdc,
    uint256 currentTotalUsdc,
    uint256 amountUsdc
) internal pure returns (uint256 updatedAmountUsdc, uint256 updatedTotalUsdc);

onlyRouter

modifier onlyRouter();

onlySettlementModule

modifier onlySettlementModule();

onlyAdmin

modifier onlyAdmin();

constructor

constructor(
    address _usdc,
    address _clearinghouse,
    uint256 _capPrice,
    CfdTypes.RiskParams memory _riskParams
) Ownable(msg.sender);

Parameters

NameTypeDescription
_usdcaddressUSDC token used as margin and settlement currency
_clearinghouseaddressMargin clearinghouse that custodies trader balances
_capPriceuint256Maximum oracle price — positions are clamped here (also determines BULL max profit)
_riskParamsCfdTypes.RiskParamsInitial risk parameters (margin requirements, carry rate, bounty config)

setDependencies

One-time setter for planner, settlement module, and admin sidecars.

function setDependencies(
    address planner_,
    address settlementModule_,
    address admin_
) external onlyOwner;

setVault

One-time setter for the HousePool vault backing all positions

function setVault(
    address _vault
) external onlyOwner;

setOrderRouter

One-time setter for the authorized OrderRouter

function setOrderRouter(
    address _router
) external onlyOwner;

withdrawFees

Withdraws accumulated execution fees from the vault to a recipient.

function withdrawFees(
    address recipient
) external onlyOwner;

withdrawFees

Withdraws up to amountUsdc of accumulated execution fees from the vault to a recipient.

function withdrawFees(
    address recipient,
    uint256 amountUsdc
) public onlyOwner;

absorbRouterCancellationFee

Pulls router-custodied cancellation fees into the vault and books them as protocol revenue.

function absorbRouterCancellationFee(
    uint256 amountUsdc
) external onlyRouter;

recordRouterProtocolFee

Books router-delivered protocol-owned inflow as protocol fees after the router has already funded the vault.

function recordRouterProtocolFee(
    uint256 amountUsdc
) external onlyRouter;

creditKeeperExecutionBounty

Credits a router-collected execution bounty into the beneficiary’s clearinghouse account.

Realizes carry first when the beneficiary currently has an open position because the clearinghouse settlement credit changes the carry basis. Router execution already validates the oracle publish time, so this helper only enforces monotonic publish ordering before checkpointing against the validated cached mark.

function creditKeeperExecutionBounty(
    address beneficiary,
    uint256 amountUsdc,
    uint256 price,
    uint64 publishTime
) external onlyRouter nonReentrant;

addMargin

Adds isolated margin to an existing open position without changing size.

function addMargin(
    bytes32 accountId,
    uint256 amount
) external nonReentrant;

realizeCarryBeforeMarginChange

Realizes accrued carry before a user-level clearinghouse balance mutation changes the carry basis.

Called only by the clearinghouse before user deposits and withdrawals.

function realizeCarryBeforeMarginChange(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) external nonReentrant;

checkpointCarryUsingStoredMark

Checkpoints carry against the cached stored mark when fresh-mark liveness is unavailable.

Restricted to the clearinghouse stale-deposit path so deposits preserve pre-mutation carry basis.

function checkpointCarryUsingStoredMark(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) external nonReentrant;

claimDeferredTraderCredit

Claims deferred trader credit balance into the clearinghouse.

The claim can be partial if current vault cash is insufficient. Funds are credited to the clearinghouse first, so beneficiaries access them through the normal account-balance path. Carry is checkpointed before the settlement-basis change using a fresh mark when available, otherwise the cached stored mark is used.

function claimDeferredTraderCredit(
    bytes32 accountId
) external nonReentrant;

claimDeferredKeeperCredit

Claims previously deferred keeper credit when the vault has replenished cash.

Deferred keeper value always settles to clearinghouse credit for the recorded keeper address-derived account.

function claimDeferredKeeperCredit() external nonReentrant;

recordDeferredKeeperCredit

Records keeper credit that could not be serviced immediately because vault cash was unavailable.

function recordDeferredKeeperCredit(
    address keeper,
    uint256 amountUsdc
) external onlyRouter;

reserveCloseOrderExecutionBounty

function reserveCloseOrderExecutionBounty(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 amountUsdc,
    address recipient
) external onlyRouter;

clearBadDebt

Reduces accumulated bad debt after governance-confirmed recapitalization

function clearBadDebt(
    uint256 amount
) external onlyOwner;

Parameters

NameTypeDescription
amountuint256USDC amount of bad debt to clear (6 decimals)

sweepToken

function sweepToken(
    address token,
    address to,
    uint256 amount
) external onlyOwner;

clearDegradedMode

function clearDegradedMode() external onlyOwner;

applyRiskConfig

function applyRiskConfig(
    ICfdEngineAdminHost.EngineRiskConfig calldata config
) external onlyAdmin;

applyCalendarConfig

function applyCalendarConfig(
    ICfdEngineAdminHost.EngineCalendarConfig calldata config
) external onlyAdmin;

applyFreshnessConfig

function applyFreshnessConfig(
    ICfdEngineAdminHost.EngineFreshnessConfig calldata config
) external onlyAdmin;

checkWithdraw

Reverts if the account has an open position that would be undercollateralized after withdrawal

function checkWithdraw(
    bytes32 accountId
) external override nonReentrant;

Parameters

NameTypeDescription
accountIdbytes32Clearinghouse account to check

processOrderTyped

Router-facing order execution entrypoint with typed business-rule failures.

function processOrderTyped(
    CfdTypes.Order memory order,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external onlyRouter nonReentrant;

_processOrder

function _processOrder(
    CfdTypes.Order memory order,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) internal;

_syncTotalSideMargin

function _syncTotalSideMargin(
    CfdTypes.Side side,
    uint256 marginBefore,
    uint256 marginAfter
) internal;

_syncMarginQueue

function _syncMarginQueue(
    bytes32 accountId,
    uint256 consumedCommittedReservationUsdc
) internal;

_payOrRecordDeferredTraderPayout

function _payOrRecordDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_enqueueOrAccrueDeferredTraderPayout

function _enqueueOrAccrueDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_enqueueOrAccrueDeferredKeeperCredit

function _enqueueOrAccrueDeferredKeeperCredit(
    address keeper,
    uint256 amountUsdc
) internal;

_canPayFreshVaultPayout

function _canPayFreshVaultPayout(
    uint256 amountUsdc
) internal view returns (bool);

_canWithdrawProtocolFees

function _canWithdrawProtocolFees(
    uint256 amountUsdc
) internal view returns (bool);

_availableCashForFreshVaultPayouts

function _availableCashForFreshVaultPayouts() internal view returns (uint256);

_freshVaultReservation

function _freshVaultReservation() internal view returns (CashPriorityLib.SeniorCashReservation memory reservation);

isFadWindow

Returns true during the Friday Afternoon Deleverage (FAD) window (Friday 19:00 UTC → Sunday 22:00 UTC), on admin-configured FAD days, or within fadRunwaySeconds before an admin FAD day (deleverage runway).

function isFadWindow() public view returns (bool);

isOracleFrozen

Returns true only when FX markets are closed and oracle freshness can be relaxed. Distinct from FAD, which starts earlier for deleveraging risk controls.

function isOracleFrozen() public view returns (bool);

positions

function positions(
    bytes32 accountId
)
    external
    view
    returns (
        uint256 size,
        uint256 margin,
        uint256 entryPrice,
        uint256 maxProfitUsdc,
        CfdTypes.Side side,
        uint64 lastUpdateTime,
        int256 vpiAccrued
    );

getPositionLastCarryTimestamp

function getPositionLastCarryTimestamp(
    bytes32 accountId
) external view returns (uint64);

liquidatePosition

Liquidates an undercollateralized position. Surplus equity (after bounty) is returned to the user. In bad-debt cases (equity < bounty), all remaining margin is seized by the vault.

function liquidatePosition(
    bytes32 accountId,
    uint256 currentOraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) external onlyRouter nonReentrant returns (uint256 keeperBountyUsdc);

Parameters

NameTypeDescription
accountIdbytes32Clearinghouse account that owns the position
currentOraclePriceuint256Pyth oracle price (8 decimals), clamped to CAP_PRICE
vaultDepthUsdcuint256HousePool total assets used for post-op solvency checks and payout affordability
publishTimeuint64Pyth publish timestamp, stored as lastMarkTime

Returns

NameTypeDescription
keeperBountyUsdcuint256Bounty paid to the liquidation keeper (USDC, 6 decimals)

_assertPostSolvency

function _assertPostSolvency() internal view;

_maxLiability

function _maxLiability() internal view returns (uint256);

_getWithdrawalReservedUsdc

function _getWithdrawalReservedUsdc() internal view returns (uint256 reservedUsdc);

_buildAdjustedSolvencyState

function _buildAdjustedSolvencyState() internal view returns (SolvencyAccountingLib.SolvencyState memory);

_buildAdjustedSolvencySnapshot

function _buildAdjustedSolvencySnapshot()
    internal
    view
    returns (CfdEngineSnapshotsLib.SolvencySnapshot memory snapshot);

_buildRawSnapshot

function _buildRawSnapshot(
    bytes32 accountId,
    uint256,
    uint256 vaultDepthUsdc,
    uint64
) internal view returns (CfdEnginePlanTypes.RawSnapshot memory snap);

_copySideSnapshot

function _copySideSnapshot(
    SideState storage state
) internal view returns (CfdEnginePlanTypes.SideSnapshot memory snap);

_tryGetFreshLiveMarkPrice

function _tryGetFreshLiveMarkPrice() internal view returns (bool fresh, uint256 price);

_revertIfOpenInvalidTyped

function _revertIfOpenInvalidTyped(
    CfdEnginePlanTypes.OpenRevertCode code
) internal view;

_revertIfCloseInvalidTyped

function _revertIfCloseInvalidTyped(
    CfdEnginePlanTypes.CloseRevertCode code
) internal view;

_applyFundingAndMark

function _applyFundingAndMark(
    uint256 newMarkPrice,
    uint64 newMarkTime
) internal;

settlementApplyFundingAndMark

function settlementApplyFundingAndMark(
    uint256 newMarkPrice,
    uint64 newMarkTime
) external onlySettlementModule;

settlementSyncTotalSideMargin

function settlementSyncTotalSideMargin(
    CfdTypes.Side side,
    uint256 marginBefore,
    uint256 marginAfter
) external onlySettlementModule;

settlementApplySideDelta

function settlementApplySideDelta(
    CfdTypes.Side side,
    int256 maxProfitDelta,
    int256 openInterestDelta,
    int256 entryNotionalDelta
) external onlySettlementModule;

settlementConsumeDeferredTraderPayout

function settlementConsumeDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) external onlySettlementModule;

settlementRecordDeferredTraderPayout

function settlementRecordDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) external onlySettlementModule;

settlementAccumulateFees

function settlementAccumulateFees(
    uint256 amountUsdc
) external onlySettlementModule;

settlementAccumulateBadDebt

function settlementAccumulateBadDebt(
    uint256 amountUsdc
) external onlySettlementModule;

settlementWritePosition

function settlementWritePosition(
    bytes32 accountId,
    CfdEngineSettlementTypes.PositionState calldata position
) external onlySettlementModule;

settlementDeletePosition

function settlementDeletePosition(
    bytes32 accountId
) external onlySettlementModule;

_applyOpen

function _applyOpen(
    CfdEnginePlanTypes.OpenDelta memory delta,
    uint64 publishTime
) internal;

_applyClose

function _applyClose(
    CfdEnginePlanTypes.CloseDelta memory delta,
    uint64 publishTime
) internal;

_applyLiquidation

function _applyLiquidation(
    CfdEnginePlanTypes.LiquidationDelta memory delta,
    uint64 publishTime
) internal returns (uint256 keeperBountyUsdc);

_enterDegradedModeIfInsolvent

function _enterDegradedModeIfInsolvent(
    bytes32 accountId,
    uint256 pendingVaultPayoutUsdc
) internal;

_genericReachableCollateralUsdc

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

_terminalReachableCollateralUsdc

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

_positionMarginBucketUsdc

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

_loadPosition

function _loadPosition(
    bytes32 accountId
) internal view returns (CfdTypes.Position memory pos);

_elapsedCarryUsdc

function _elapsedCarryUsdc(
    CfdTypes.Position memory pos,
    uint256 price,
    uint256 reachableCollateralUsdc,
    uint256 timestampNow
) internal view returns (uint256);

_totalPendingCarryUsdc

function _totalPendingCarryUsdc(
    bytes32 accountId,
    CfdTypes.Position memory pos,
    uint256 price,
    uint256 reachableCollateralUsdc,
    uint256 timestampNow
) internal view returns (uint256);

_canFullyRealizeCarryFromSettlement

function _canFullyRealizeCarryFromSettlement(
    bytes32 accountId,
    CfdTypes.Position memory pos,
    uint256 price
) internal view returns (bool);

_checkpointCarryBeforeBasisChange

function _checkpointCarryBeforeBasisChange(
    bytes32 accountId,
    StoredPosition storage pos,
    uint256 price,
    uint256 reachableCollateralUsdc
) internal;

_realizeCarryFromSettlement

function _realizeCarryFromSettlement(
    bytes32 accountId,
    StoredPosition storage pos,
    uint256 price,
    uint256 reachableCollateralUsdc
) internal returns (uint256 realizedCarryUsdc);

_liveMarkStalenessLimit

function _liveMarkStalenessLimit() internal view returns (uint256);

_consumeDeferredTraderPayout

function _consumeDeferredTraderPayout(
    bytes32 accountId,
    uint256 amountUsdc
) internal;

_validateRiskParams

function _validateRiskParams(
    CfdTypes.RiskParams memory _riskParams
) internal pure;

updateMarkPrice

Updates the cached mark price without processing a trade or liquidation.

This does not itself realize carry; carry realization happens on execution and margin-mutating paths.

function updateMarkPrice(
    uint256 price,
    uint64 publishTime
) external onlyRouter;

Parameters

NameTypeDescription
priceuint256Oracle price (8 decimals), clamped to CAP_PRICE
publishTimeuint64Pyth publish timestamp

_getVaultMtmLiability

function _getVaultMtmLiability() internal view returns (uint256);

_getProtocolPhase

function _getProtocolPhase() internal view returns (ICfdEngine.ProtocolPhase);

getProtocolStatus

function getProtocolStatus() external view returns (EngineStatusViewTypes.ProtocolStatus memory status);

Events

FundingUpdated

event FundingUpdated(int256 bullIndex, int256 bearIndex, uint256 absSkewUsdc);

PositionOpened

event PositionOpened(
    bytes32 indexed accountId, CfdTypes.Side side, uint256 sizeDelta, uint256 price, uint256 marginDelta
);

PositionClosed

event PositionClosed(bytes32 indexed accountId, CfdTypes.Side side, uint256 sizeDelta, uint256 price, int256 pnl);

PositionLiquidated

event PositionLiquidated(
    bytes32 indexed accountId, CfdTypes.Side side, uint256 size, uint256 price, uint256 keeperBounty
);

MarginAdded

event MarginAdded(bytes32 indexed accountId, uint256 amount);

FadDaysAdded

event FadDaysAdded(uint256[] timestamps);

FadDaysRemoved

event FadDaysRemoved(uint256[] timestamps);

FadMaxStalenessUpdated

event FadMaxStalenessUpdated(uint256 newStaleness);

FadRunwayUpdated

event FadRunwayUpdated(uint256 newRunway);

EngineMarkStalenessLimitUpdated

event EngineMarkStalenessLimitUpdated(uint256 newStaleness);

BadDebtCleared

event BadDebtCleared(uint256 amount, uint256 remaining);

DegradedModeEntered

event DegradedModeEntered(uint256 effectiveAssets, uint256 maxLiability, bytes32 indexed triggeringAccount);

DegradedModeCleared

event DegradedModeCleared();

DeferredTraderCreditRecorded

event DeferredTraderCreditRecorded(bytes32 indexed accountId, uint256 amountUsdc);

DeferredTraderCreditClaimed

event DeferredTraderCreditClaimed(bytes32 indexed accountId, uint256 amountUsdc);

DeferredKeeperCreditRecorded

event DeferredKeeperCreditRecorded(address indexed keeper, uint256 amountUsdc);

DeferredKeeperCreditClaimed

event DeferredKeeperCreditClaimed(address indexed keeper, uint256 amountUsdc);

CarryCheckpointed

event CarryCheckpointed(
    bytes32 indexed accountId, uint256 addedUnsettledCarryUsdc, uint256 totalUnsettledCarryUsdc
);

CarryRealized

event CarryRealized(
    bytes32 indexed accountId,
    uint256 realizedCarryUsdc,
    uint256 freeSettlementConsumedUsdc,
    uint256 marginConsumedUsdc,
    uint256 remainingUnsettledCarryUsdc
);

TokenSwept

event TokenSwept(address indexed token, address indexed to, uint256 amount);

Errors

CfdEngine__Unauthorized

error CfdEngine__Unauthorized();

CfdEngine__VaultAlreadySet

error CfdEngine__VaultAlreadySet();

CfdEngine__RouterAlreadySet

error CfdEngine__RouterAlreadySet();

CfdEngine__DependenciesAlreadySet

error CfdEngine__DependenciesAlreadySet();

CfdEngine__NoFeesToWithdraw

error CfdEngine__NoFeesToWithdraw();

CfdEngine__NoDeferredTraderCredit

error CfdEngine__NoDeferredTraderCredit();

CfdEngine__InsufficientVaultLiquidity

error CfdEngine__InsufficientVaultLiquidity();

CfdEngine__NoDeferredKeeperCredit

error CfdEngine__NoDeferredKeeperCredit();

CfdEngine__MustCloseOpposingPosition

error CfdEngine__MustCloseOpposingPosition();

CfdEngine__FundingExceedsMargin

error CfdEngine__FundingExceedsMargin();

CfdEngine__VaultSolvencyExceeded

error CfdEngine__VaultSolvencyExceeded();

CfdEngine__MarginDrainedByFees

error CfdEngine__MarginDrainedByFees();

CfdEngine__CloseSizeExceedsPosition

error CfdEngine__CloseSizeExceedsPosition();

CfdEngine__NoPositionToLiquidate

error CfdEngine__NoPositionToLiquidate();

CfdEngine__PositionIsSolvent

error CfdEngine__PositionIsSolvent();

CfdEngine__PostOpSolvencyBreach

error CfdEngine__PostOpSolvencyBreach();

CfdEngine__InsufficientInitialMargin

error CfdEngine__InsufficientInitialMargin();

CfdEngine__PositionTooSmall

error CfdEngine__PositionTooSmall();

CfdEngine__WithdrawBlockedByOpenPosition

error CfdEngine__WithdrawBlockedByOpenPosition();

CfdEngine__EmptyDays

error CfdEngine__EmptyDays();

CfdEngine__ZeroStaleness

error CfdEngine__ZeroStaleness();

CfdEngine__ZeroAmount

error CfdEngine__ZeroAmount();

CfdEngine__RunwayTooLong

error CfdEngine__RunwayTooLong();

CfdEngine__PartialCloseUnderwaterFunding

error CfdEngine__PartialCloseUnderwaterFunding();

CfdEngine__DustPosition

error CfdEngine__DustPosition();

CfdEngine__MarkPriceStale

error CfdEngine__MarkPriceStale();

CfdEngine__MarkPriceOutOfOrder

error CfdEngine__MarkPriceOutOfOrder();

CfdEngine__NotClearinghouse

error CfdEngine__NotClearinghouse();

CfdEngine__NotAccountOwner

error CfdEngine__NotAccountOwner();

CfdEngine__NoOpenPosition

error CfdEngine__NoOpenPosition();

CfdEngine__BadDebtTooLarge

error CfdEngine__BadDebtTooLarge();

CfdEngine__InvalidRiskParams

error CfdEngine__InvalidRiskParams();

CfdEngine__SkewTooHigh

error CfdEngine__SkewTooHigh();

CfdEngine__DegradedMode

error CfdEngine__DegradedMode();

CfdEngine__NotDegraded

error CfdEngine__NotDegraded();

CfdEngine__StillInsolvent

error CfdEngine__StillInsolvent();

CfdEngine__ZeroAddress

error CfdEngine__ZeroAddress();

CfdEngine__InsufficientCloseOrderBountyBacking

error CfdEngine__InsufficientCloseOrderBountyBacking();

Structs

AccountCollateralView

struct AccountCollateralView {
    uint256 settlementBalanceUsdc;
    uint256 lockedMarginUsdc;
    // Clearinghouse custody bucket for currently locked live position backing.
    uint256 activePositionMarginUsdc;
    uint256 otherLockedMarginUsdc;
    uint256 freeSettlementUsdc;
    // Current UI helper only; this does not include terminally reachable queued committed margin.
    uint256 closeReachableUsdc;
    uint256 terminalReachableUsdc;
    uint256 accountEquityUsdc;
    uint256 freeBuyingPowerUsdc;
    uint256 deferredTraderCreditUsdc;
}

PositionView

struct PositionView {
    bool exists;
    CfdTypes.Side side;
    uint256 size;
    uint256 margin;
    uint256 entryPrice;
    uint256 entryNotionalUsdc;
    uint256 physicalReachableCollateralUsdc;
    uint256 nettableDeferredTraderCreditUsdc;
    int256 unrealizedPnlUsdc;
    int256 netEquityUsdc;
    uint256 maxProfitUsdc;
    bool liquidatable;
}

ProtocolAccountingView

struct ProtocolAccountingView {
    uint256 vaultAssetsUsdc;
    uint256 maxLiabilityUsdc;
    uint256 withdrawalReservedUsdc;
    uint256 freeUsdc;
    uint256 accumulatedFeesUsdc;
    uint256 totalDeferredTraderCreditUsdc;
    uint256 totalDeferredKeeperCreditUsdc;
    bool degradedMode;
    bool hasLiveLiability;
}

ClosePreview

struct ClosePreview {
    bool valid;
    CfdTypes.CloseInvalidReason invalidReason;
    uint256 executionPrice;
    uint256 sizeDelta;
    int256 realizedPnlUsdc;
    int256 vpiDeltaUsdc;
    uint256 vpiUsdc;
    uint256 executionFeeUsdc;
    uint256 freshTraderPayoutUsdc;
    uint256 existingDeferredConsumedUsdc;
    uint256 existingDeferredRemainingUsdc;
    uint256 immediatePayoutUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 seizedCollateralUsdc;
    uint256 badDebtUsdc;
    uint256 remainingSize;
    uint256 remainingMargin;
    bool triggersDegradedMode;
    bool postOpDegradedMode;
    uint256 effectiveAssetsAfterUsdc;
    uint256 maxLiabilityAfterUsdc;
}

LiquidationPreview

struct LiquidationPreview {
    bool liquidatable;
    uint256 oraclePrice;
    int256 equityUsdc;
    int256 pnlUsdc;
    uint256 reachableCollateralUsdc;
    uint256 keeperBountyUsdc;
    uint256 seizedCollateralUsdc;
    uint256 settlementRetainedUsdc;
    uint256 freshTraderPayoutUsdc;
    uint256 existingDeferredConsumedUsdc;
    uint256 existingDeferredRemainingUsdc;
    uint256 immediatePayoutUsdc;
    uint256 deferredTraderCreditUsdc;
    uint256 badDebtUsdc;
    bool triggersDegradedMode;
    bool postOpDegradedMode;
    uint256 effectiveAssetsAfterUsdc;
    uint256 maxLiabilityAfterUsdc;
}

DeferredCreditStatus

struct DeferredCreditStatus {
    uint256 deferredTraderCreditUsdc;
    bool traderPayoutClaimableNow;
    uint256 deferredKeeperCreditUsdc;
    bool keeperCreditClaimableNow;
}

SideState

struct SideState {
    uint256 maxProfitUsdc;
    uint256 openInterest;
    uint256 entryNotional;
    // Cached aggregate of engine economic position margins for this side; not a custody bucket.
    uint256 totalMargin;
}

StoredPosition

struct StoredPosition {
    uint256 size;
    uint256 entryPrice;
    uint256 maxProfitUsdc;
    CfdTypes.Side side;
    uint64 lastUpdateTime;
    uint64 lastCarryTimestamp;
    int256 vpiAccrued;
}

CfdEngineAccountLens

Git Source

Inherits: ICfdEngineAccountLens

Title: CfdEngineAccountLens

Rich per-account diagnostic lens for audits, tests, and operator tooling.

This is intentionally wider than the product-facing PerpsPublicLens surface.

Constants

engineContract

CfdEngine public immutable engineContract;

Functions

constructor

constructor(
    address engine_
);

Parameters

NameTypeDescription
engine_addressDeployed CfdEngine instance to inspect.

getAccountCollateralView

Returns detailed clearinghouse bucket and reachability state for an account.

function getAccountCollateralView(
    bytes32 accountId
) external view returns (CfdEngine.AccountCollateralView memory viewData);

getWithdrawableUsdc

Returns the current withdrawable USDC for an account under engine-side guards.

Open-position withdrawals are limited by free buying power, degraded mode, mark freshness, pending carry, and the post-withdraw initial margin requirement.

function getWithdrawableUsdc(
    bytes32 accountId
) external view returns (uint256 withdrawableUsdc);

getAccountLedgerView

Returns a compact accounting split for account custody, escrow, and deferred balances.

function getAccountLedgerView(
    bytes32 accountId
) external view returns (AccountLensViewTypes.AccountLedgerView memory viewData);

getAccountLedgerSnapshot

Returns the full account ledger snapshot used by tests and richer read paths.

function getAccountLedgerSnapshot(
    bytes32 accountId
) external view returns (AccountLensViewTypes.AccountLedgerSnapshot memory snapshot);

_buildAccountLedgerSnapshot

function _buildAccountLedgerSnapshot(
    bytes32 accountId
) internal view returns (AccountLensViewTypes.AccountLedgerSnapshot memory snapshot);

_position

function _position(
    bytes32 accountId
) internal view returns (CfdTypes.Position memory pos);

_riskParams

function _riskParams() internal view returns (CfdTypes.RiskParams memory params);

CfdEngineAdmin

Git Source

Inherits: Ownable

Constants

TIMELOCK_DELAY

uint256 public constant TIMELOCK_DELAY = 48 hours;

engine

ICfdEngineAdminHost public immutable engine;

State Variables

pendingRiskConfig

ICfdEngineAdminHost.EngineRiskConfig public pendingRiskConfig;

riskConfigActivationTime

uint256 public riskConfigActivationTime;

_pendingCalendarConfig

ICfdEngineAdminHost.EngineCalendarConfig private _pendingCalendarConfig;

calendarConfigActivationTime

uint256 public calendarConfigActivationTime;

pendingFreshnessConfig

ICfdEngineAdminHost.EngineFreshnessConfig public pendingFreshnessConfig;

freshnessConfigActivationTime

uint256 public freshnessConfigActivationTime;

Functions

constructor

constructor(
    address engine_,
    address initialOwner
) Ownable(initialOwner);

proposeRiskConfig

function proposeRiskConfig(
    ICfdEngineAdminHost.EngineRiskConfig calldata config
) external onlyOwner;

finalizeRiskConfig

function finalizeRiskConfig() external onlyOwner;

cancelRiskConfig

function cancelRiskConfig() external onlyOwner;

proposeCalendarConfig

function proposeCalendarConfig(
    ICfdEngineAdminHost.EngineCalendarConfig calldata config
) external onlyOwner;

finalizeCalendarConfig

function finalizeCalendarConfig() external onlyOwner;

cancelCalendarConfig

function cancelCalendarConfig() external onlyOwner;

getPendingCalendarConfig

function getPendingCalendarConfig() external view returns (ICfdEngineAdminHost.EngineCalendarConfig memory config);

proposeFreshnessConfig

function proposeFreshnessConfig(
    ICfdEngineAdminHost.EngineFreshnessConfig calldata config
) external onlyOwner;

finalizeFreshnessConfig

function finalizeFreshnessConfig() external onlyOwner;

cancelFreshnessConfig

function cancelFreshnessConfig() external onlyOwner;

_requireTimelockReady

function _requireTimelockReady(
    uint256 activationTime
) internal view;

_validateRiskParams

function _validateRiskParams(
    CfdTypes.RiskParams memory riskParams_
) internal pure;

Events

RiskConfigProposed

event RiskConfigProposed(ICfdEngineAdminHost.EngineRiskConfig config, uint256 activationTime);

RiskConfigFinalized

event RiskConfigFinalized(ICfdEngineAdminHost.EngineRiskConfig config);

RiskConfigCancelled

event RiskConfigCancelled();

CalendarConfigProposed

event CalendarConfigProposed(ICfdEngineAdminHost.EngineCalendarConfig config, uint256 activationTime);

CalendarConfigFinalized

event CalendarConfigFinalized(ICfdEngineAdminHost.EngineCalendarConfig config);

CalendarConfigCancelled

event CalendarConfigCancelled();

FreshnessConfigProposed

event FreshnessConfigProposed(ICfdEngineAdminHost.EngineFreshnessConfig config, uint256 activationTime);

FreshnessConfigFinalized

event FreshnessConfigFinalized(ICfdEngineAdminHost.EngineFreshnessConfig config);

FreshnessConfigCancelled

event FreshnessConfigCancelled();

Errors

CfdEngineAdmin__NoProposal

error CfdEngineAdmin__NoProposal();

CfdEngineAdmin__TimelockNotReady

error CfdEngineAdmin__TimelockNotReady();

CfdEngineAdmin__ZeroStaleness

error CfdEngineAdmin__ZeroStaleness();

CfdEngineAdmin__RunwayTooLong

error CfdEngineAdmin__RunwayTooLong();

CfdEngineAdmin__InvalidRiskParams

error CfdEngineAdmin__InvalidRiskParams();

CfdEngineAdmin__InvalidExecutionFee

error CfdEngineAdmin__InvalidExecutionFee();

CfdEngineLens

Git Source

Inherits: ICfdEngineLens

Constants

engineContract

CfdEngine public immutable engineContract;

Functions

constructor

constructor(
    address engine_
);

engine

function engine() external view returns (address);

previewClose

function previewClose(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 oraclePrice
) external view returns (CfdEngine.ClosePreview memory preview);

previewOpenRevertCode

function previewOpenRevertCode(
    bytes32 accountId,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 oraclePrice,
    uint64 publishTime
) external view returns (uint8 code);

previewOpenFailurePolicyCategory

function previewOpenFailurePolicyCategory(
    bytes32 accountId,
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 oraclePrice,
    uint64 publishTime
) external view returns (CfdEnginePlanTypes.OpenFailurePolicyCategory category);

simulateClose

function simulateClose(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) external view returns (CfdEngine.ClosePreview memory preview);

previewLiquidation

function previewLiquidation(
    bytes32 accountId,
    uint256 oraclePrice
) external view returns (CfdEngine.LiquidationPreview memory preview);

simulateLiquidation

function simulateLiquidation(
    bytes32 accountId,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) external view returns (CfdEngine.LiquidationPreview memory preview);

_previewClose

function _previewClose(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) internal view returns (CfdEngine.ClosePreview memory preview);

_previewLiquidation

function _previewLiquidation(
    bytes32 accountId,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc
) internal view returns (CfdEngine.LiquidationPreview memory preview);

_buildRawSnapshot

function _buildRawSnapshot(
    bytes32 accountId,
    uint256 oraclePrice,
    uint256 vaultDepthUsdc,
    uint64 publishTime
) internal view returns (CfdEnginePlanTypes.RawSnapshot memory snap);

_applyLiquidationPreviewForfeiture

function _applyLiquidationPreviewForfeiture(
    bytes32 accountId,
    CfdEnginePlanTypes.RawSnapshot memory snap
) internal view;

_position

function _position(
    bytes32 accountId
) internal view returns (CfdTypes.Position memory pos);

_sideSnapshot

function _sideSnapshot(
    ICfdEngine.SideState memory side
) internal pure returns (CfdEnginePlanTypes.SideSnapshot memory snap);

_riskParams

function _riskParams() internal view returns (CfdTypes.RiskParams memory params);

CfdEnginePlanTypes

Git Source

Title: CfdEnginePlanTypes

Snapshot and delta structs for the plan→apply architecture. Plan functions are pure over a RawSnapshot and return typed deltas. Apply functions consume deltas to perform state mutations and external calls.

Structs

SideSnapshot

struct SideSnapshot {
    uint256 maxProfitUsdc;
    uint256 openInterest;
    uint256 entryNotional;
    uint256 totalMargin;
}

RawSnapshot

struct RawSnapshot {
    CfdTypes.Position position;
    bytes32 accountId;

    uint256 currentTimestamp;
    uint256 lastMarkPrice;
    uint64 lastMarkTime;

    SideSnapshot bullSide;
    SideSnapshot bearSide;

    uint256 vaultAssetsUsdc;
    uint256 vaultCashUsdc;

    IMarginClearinghouse.AccountUsdcBuckets accountBuckets;
    IMarginClearinghouse.LockedMarginBuckets lockedBuckets;

    uint64[] marginReservationIds;

    uint256 accumulatedFeesUsdc;
    uint256 accumulatedBadDebtUsdc;
    uint256 unsettledCarryUsdc;
    uint256 totalDeferredTraderCreditUsdc;
    uint256 totalDeferredKeeperCreditUsdc;
    uint256 deferredTraderCreditForAccount;
    bool degradedMode;

    uint256 capPrice;
    CfdTypes.RiskParams riskParams;
    uint256 executionFeeBps;
    bool isFadWindow;
}

SolvencyPreview

struct SolvencyPreview {
    uint256 effectiveAssetsAfterUsdc;
    uint256 maxLiabilityAfterUsdc;
    bool triggersDegradedMode;
    bool postOpDegradedMode;
}

OpenDelta

struct OpenDelta {
    bool valid;
    OpenRevertCode revertCode;

    OpenAccountingLib.OpenState openState;

    CfdTypes.Side posSide;
    uint256 newPosSize;
    uint256 newPosEntryPrice;
    int256 posVpiAccruedDelta;
    uint256 posMaxProfitIncrease;
    uint256 positionMarginAfterOpen;

    uint256 sideOiIncrease;
    int256 sideEntryNotionalDelta;
    int256 sideEntryFundingContribution;
    uint256 sideMaxProfitIncrease;

    int256 tradeCostUsdc;
    uint256 marginDeltaUsdc;
    int256 netMarginChange;
    uint256 vaultRebatePayoutUsdc;

    uint256 executionFeeUsdc;
    uint256 pendingCarryUsdc;

    uint256 sideTotalMarginBefore;
    uint256 sideTotalMarginAfterOpen;

    bytes32 accountId;
    uint256 sizeDelta;
    uint256 price;
}

CloseDelta

struct CloseDelta {
    bool valid;
    CloseRevertCode revertCode;

    CloseAccountingLib.CloseState closeState;
    uint256 postBullOi;
    uint256 postBearOi;

    uint256 posMarginAfter;
    uint256 posSizeDelta;
    uint256 posMaxProfitReduction;
    int256 posVpiAccruedReduction;
    bool deletePosition;

    CfdTypes.Side side;
    uint256 sideOiDecrease;
    uint256 sideEntryNotionalReduction;
    uint256 sideMaxProfitReduction;

    uint256 unlockMarginUsdc;

    SettlementType settlementType;
    uint256 lossUsdc;

    uint256 freshTraderPayoutUsdc;
    bool freshPayoutIsImmediate;
    bool freshPayoutIsDeferred;
    uint256 existingDeferredConsumedUsdc;
    uint256 existingDeferredRemainingUsdc;
    uint256 deferredFeeRecoveryUsdc;

    CfdEngineSettlementLib.CloseSettlementResult lossResult;
    MarginClearinghouseAccountingLib.SettlementConsumption lossConsumption;
    uint256 syncMarginQueueAmount;

    uint256 executionFeeUsdc;
    uint256 badDebtUsdc;
    uint256 pendingCarryUsdc;

    uint256 totalMarginBefore;
    uint256 totalMarginAfterClose;

    SolvencyPreview solvency;

    bytes32 accountId;
    uint256 sizeDelta;
    uint256 price;
    int256 realizedPnlUsdc;
}

LiquidationDelta

struct LiquidationDelta {
    bool liquidatable;

    PositionRiskAccountingLib.PositionRiskState riskState;
    LiquidationAccountingLib.LiquidationState liquidationState;

    CfdTypes.Side side;
    uint256 posSize;
    uint256 posMargin;
    uint256 posMaxProfit;
    uint256 posEntryPrice;

    uint256 sideOiDecrease;
    uint256 sideMaxProfitDecrease;
    uint256 sideEntryNotionalReduction;
    uint256 sideTotalMarginReduction;

    uint256 keeperBountyUsdc;
    uint256 liquidationReachableCollateralUsdc;

    int256 residualUsdc;
    MarginClearinghouseAccountingLib.LiquidationResidualPlan residualPlan;

    uint256 settlementRetainedUsdc;
    uint256 freshTraderPayoutUsdc;
    bool freshPayoutIsImmediate;
    bool freshPayoutIsDeferred;
    uint256 existingDeferredConsumedUsdc;
    uint256 existingDeferredRemainingUsdc;

    uint256 syncMarginQueueAmount;

    uint256 badDebtUsdc;
    uint256 pendingCarryUsdc;

    SolvencyPreview solvency;

    bytes32 accountId;
    uint256 price;
}

Enums

OpenFailurePolicyCategory

enum OpenFailurePolicyCategory {
    None,
    CommitTimeRejectable,
    ExecutionTimeUserInvalid,
    ExecutionTimeProtocolStateInvalidated
}

ExecutionFailurePolicyCategory

enum ExecutionFailurePolicyCategory {
    None,
    UserInvalid,
    ProtocolStateInvalidated
}

OpenRevertCode

enum OpenRevertCode {
    OK,
    MUST_CLOSE_OPPOSING,
    DEGRADED_MODE,
    POSITION_TOO_SMALL,
    SKEW_TOO_HIGH,
    MARGIN_DRAINED_BY_FEES,
    INSUFFICIENT_INITIAL_MARGIN,
    SOLVENCY_EXCEEDED
}

CloseRevertCode

enum CloseRevertCode {
    OK,
    CLOSE_SIZE_EXCEEDS,
    DUST_POSITION,
    PARTIAL_CLOSE_UNDERWATER
}

SettlementType

enum SettlementType {
    ZERO,
    GAIN,
    LOSS
}

CfdEnginePlanner

Git Source

Inherits: ICfdEnginePlanner

Functions

computeOpenMarginAfter

function computeOpenMarginAfter(
    uint256 marginAfterFunding,
    int256 netMarginChange
) external pure returns (bool drained, uint256 marginAfter);

planOpen

function planOpen(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.OpenDelta memory delta);

planClose

function planClose(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    CfdTypes.Order memory order,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.CloseDelta memory delta);

planLiquidation

function planLiquidation(
    CfdEnginePlanTypes.RawSnapshot memory snap,
    uint256 executionPrice,
    uint64 publishTime
) external pure returns (CfdEnginePlanTypes.LiquidationDelta memory delta);

getOpenFailurePolicyCategory

function getOpenFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) external pure returns (CfdEnginePlanTypes.OpenFailurePolicyCategory);

getExecutionFailurePolicyCategory

function getExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.OpenRevertCode code
) external pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

getCloseExecutionFailurePolicyCategory

function getCloseExecutionFailurePolicyCategory(
    CfdEnginePlanTypes.CloseRevertCode code
) external pure returns (CfdEnginePlanTypes.ExecutionFailurePolicyCategory);

CfdEngineProtocolLens

Git Source

Inherits: ICfdEngineProtocolLens

Title: CfdEngineProtocolLens

Rich protocol-accounting lens for audits, tests, and HousePool integration.

Exposes conservative solvency and liability views rather than product-level summaries.

Constants

engineContract

CfdEngine public immutable engineContract;

Functions

constructor

constructor(
    address engine_
);

Parameters

NameTypeDescription
engine_addressDeployed CfdEngine instance to inspect.

getProtocolAccountingSnapshot

Returns the canonical protocol-accounting snapshot used by diagnostics and audits.

function getProtocolAccountingSnapshot()
    external
    view
    returns (ProtocolLensViewTypes.ProtocolAccountingSnapshot memory snapshot);

getHousePoolInputSnapshot

Builds the HousePool accounting snapshot against a caller-supplied freshness limit.

This packages the engine-side values HousePool needs for reconcile and withdrawal logic.

function getHousePoolInputSnapshot(
    uint256 markStalenessLimit
) external view returns (HousePoolEngineViewTypes.HousePoolInputSnapshot memory snapshot);

getHousePoolStatusSnapshot

Returns the current HousePool status flags sourced from engine runtime state.

function getHousePoolStatusSnapshot()
    external
    view
    returns (HousePoolEngineViewTypes.HousePoolStatusSnapshot memory snapshot);

_getVaultMtmLiability

function _getVaultMtmLiability() internal view returns (uint256);

_buildProtocolAccountingSnapshot

function _buildProtocolAccountingSnapshot()
    internal
    view
    returns (ProtocolLensViewTypes.ProtocolAccountingSnapshot memory snapshot);

_buildAdjustedSolvencyState

function _buildAdjustedSolvencyState() internal view returns (SolvencyAccountingLib.SolvencyState memory);

_sideState

function _sideState(
    CfdTypes.Side side
) internal view returns (ICfdEngine.SideState memory state);

_riskParams

function _riskParams() internal view returns (CfdTypes.RiskParams memory params);

CfdEngineSettlementModule

Git Source

Inherits: ICfdEngineSettlementModule

Title: CfdEngineSettlementModule

Externalized settlement executor for CfdEngine close and liquidation flows.

CfdEngine remains the storage owner and grants this module access only through narrow settlement-host hooks. The module does not own independent protocol state.

Constants

ENGINE

address public immutable ENGINE;

Functions

constructor

constructor(
    address engine_
);

onlyEngine

modifier onlyEngine();

executeOpen

Applies the live open/increase settlement plan produced by the planner.

Realizes carry, fee, and vault-flow side effects through the settlement host while keeping the engine as the canonical state owner.

function executeOpen(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.OpenDelta calldata delta,
    CfdTypes.Position calldata currentPosition,
    uint64 publishTime
) external onlyEngine;

executeClose

Applies the live close/decrease settlement plan produced by the planner.

Can record deferred trader credit, bad debt, and realized carry depending on the close result.

function executeClose(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.CloseDelta calldata delta,
    CfdTypes.Position calldata currentPosition,
    uint64 publishTime
) external onlyEngine;

executeLiquidation

Applies the live liquidation settlement plan produced by the planner.

function executeLiquidation(
    ICfdEngineSettlementHost host,
    CfdEnginePlanTypes.LiquidationDelta calldata delta,
    uint64 publishTime
) external onlyEngine returns (uint256 keeperBountyUsdc);

Returns

NameTypeDescription
keeperBountyUsdcuint256Liquidation bounty owed to the keeper after the state transition.

Errors

CfdEngineSettlementModule__Unauthorized

error CfdEngineSettlementModule__Unauthorized();

CfdMath

Git Source

Title: CfdMath

Pure stateless math library for PnL and price impact

Note: security-contact: contact@plether.com

Constants

WAD

uint256 internal constant WAD = 1e18;

SECONDS_PER_YEAR

uint256 internal constant SECONDS_PER_YEAR = 31_536_000;

USDC_TO_TOKEN_SCALE

uint256 internal constant USDC_TO_TOKEN_SCALE = 1e20;

Functions

calculatePnL

Calculates Unrealized PnL strictly bounded by the protocol CAP

function calculatePnL(
    CfdTypes.Position memory pos,
    uint256 currentOraclePrice,
    uint256 capPrice
) internal pure returns (bool isProfit, uint256 pnlUsdc);

Parameters

NameTypeDescription
posCfdTypes.PositionThe position to evaluate
currentOraclePriceuint256Current oracle price (8 decimals)
capPriceuint256Protocol cap price (8 decimals)

Returns

NameTypeDescription
isProfitboolTrue if the position is in profit
pnlUsdcuint256Absolute PnL value in USDC (6 decimals)

calculateMaxProfit

Calculates the absolute maximum payout a trade can ever achieve

function calculateMaxProfit(
    uint256 size,
    uint256 entryPrice,
    CfdTypes.Side side,
    uint256 capPrice
) internal pure returns (uint256 maxProfitUsdc);

Parameters

NameTypeDescription
sizeuint256Notional size (18 decimals)
entryPriceuint256Entry oracle price (8 decimals)
sideCfdTypes.SideBULL or BEAR
capPriceuint256Protocol cap price (8 decimals)

Returns

NameTypeDescription
maxProfitUsdcuint256Maximum possible profit in USDC (6 decimals)

conservativeMtmLiability

Conservative upper bound for a side’s current gross winning-trader MtM liability.

Uses each position’s max-profit envelope so same-side losing positions cannot net down winning positions before their losses are physically realized.

function conservativeMtmLiability(
    uint256 maxProfitUsdc,
    CfdTypes.Side side,
    uint256 price,
    uint256 capPrice
) internal pure returns (uint256);

_getSkewCost

Calculates the cost of a specific skew state. C(S) = 0.5 * k * (S^2 / D)

function _getSkewCost(
    uint256 skewUsdc,
    uint256 depthUsdc,
    uint256 vpiFactorWad
) private pure returns (uint256 costUsdc);

Parameters

NameTypeDescription
skewUsdcuint256The absolute directional imbalance in USDC (6 decimals)
depthUsdcuint256The total free USDC in the House Pool (6 decimals)
vpiFactorWaduint256The ‘k’ impact parameter (18 decimals)

Returns

NameTypeDescription
costUsdcuint256The theoretical cost to reach this skew (6 decimals)

calculateVPI

Calculates the VPI charge/rebate for a trade.

If postCost > preCost, result is positive (Charge Trader). If postCost < preCost, result is negative (Rebate Trader / MM Incentive).

function calculateVPI(
    uint256 preSkewUsdc,
    uint256 postSkewUsdc,
    uint256 depthUsdc,
    uint256 vpiFactorWad
) internal pure returns (int256 vpiUsdc);

CfdTypes

Git Source

Title: CfdTypes

Core data structures for the Plether CFD Engine

Note: security-contact: contact@plether.com

Structs

Position

A user’s active position in a specific market.

margin is the engine’s canonical economic position-margin state used for risk and state transitions. It is intentionally distinct from the clearinghouse custody bucket that holds the locked funds backing it.

struct Position {
    uint256 size; // [18 dec] Notional size in synthetic tokens
    uint256 margin; // [6 dec] Isolated margin backing this position
    uint256 entryPrice; // [8 dec] Oracle price of BEAR at execution
    uint256 maxProfitUsdc; // [6 dec] Cumulative max profit tracked to avoid truncation underflow
    Side side; // [uint8] Trade direction
    uint64 lastUpdateTime; // [uint64] Timestamp of last modification
    uint64 lastCarryTimestamp; // [uint64] Timestamp through which carry has been realized
    int256 vpiAccrued; // [6 dec] Cumulative VPI charges (+) and rebates (-) across the position's lifetime
}

Order

An intent submitted by a user, waiting for Keeper execution

struct Order {
    bytes32 accountId; // Maps to MarginClearinghouse unified account
    uint256 sizeDelta; // [18 dec] Amount of size to add/remove
    uint256 marginDelta; // [6 dec] Amount of margin to add/remove
    uint256 targetPrice; // [8 dec] Slippage protection limit
    uint64 commitTime; // Timestamp of intent submission (MEV shield)
    uint64 commitBlock; // Block number of intent submission (same-block execution shield)
    uint64 orderId; // Strict FIFO execution queue ID
    Side side; // [uint8] BULL or BEAR
    bool isClose; // [bool] True if strictly closing/reducing
}

RiskParams

Global configuration parameters for the VPI and carry engines

struct RiskParams {
    uint256 vpiFactor; // [18 dec WAD] Impact severity 'k'
    uint256 maxSkewRatio; // [18 dec WAD] Hard cliff e.g., 40% (0.40e18)
    uint256 maintMarginBps; // e.g., 100 (1%)
    uint256 initMarginBps; // e.g., 150 (1.5%)
    uint256 fadMarginBps; // e.g., 300 (3%)
    uint256 baseCarryBps; // e.g., 500 (5% annualized carry on LP-backed notional)
    uint256 minBountyUsdc; // e.g., 1_000_000 ($1 USDC floor)
    uint256 bountyBps; // e.g., 10 (0.10% of Notional Size)
}

Enums

Side

BULL profits when USD strengthens (oracle price drops). BEAR profits when USD weakens (oracle price rises).

enum Side {
    BULL,
    BEAR
}

CloseInvalidReason

enum CloseInvalidReason {
    None,
    NoPosition,
    BadSize,
    PartialCloseUnderwater,
    DustPosition
}

HousePool

Git Source

Inherits: ICfdVault, IHousePool, IPerpsLPActions, 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

ICfdEngineCore public immutable ENGINE;

ENGINE_PROTOCOL_LENS

ICfdEngineProtocolLens public immutable ENGINE_PROTOCOL_LENS;

MAX_FROZEN_LP_FEE_BPS

uint256 public constant MAX_FROZEN_LP_FEE_BPS = 1000;

TIMELOCK_DELAY

uint256 public constant TIMELOCK_DELAY = 48 hours;

State Variables

orderRouter

address public orderRouter;

seniorVault

address public seniorVault;

juniorVault

address public juniorVault;

pauser

address public pauser;

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;

poolConfig

PoolConfig internal poolConfig;

isTradingActive

bool public override(ICfdVault, IHousePool) isTradingActive;

seniorSeedInitialized

bool public seniorSeedInitialized;

juniorSeedInitialized

bool public juniorSeedInitialized;

pendingPoolConfig

PoolConfig public pendingPoolConfig;

poolConfigActivationTime

uint256 public poolConfigActivationTime;

Functions

onlyPauserOrOwner

modifier onlyPauserOrOwner();

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;

proposePoolConfig

Propose a new pool config, subject to a 48h timelock.

function proposePoolConfig(
    PoolConfig calldata newConfig
) external onlyOwner;

finalizePoolConfig

Finalizes the proposed pool config after the timelock expires.

Senior-rate changes require a fresh mark so yield accrual cannot be rerated across a stale interval.

function finalizePoolConfig() external onlyOwner;

cancelPoolConfigProposal

Cancel the pending pool config proposal.

function cancelPoolConfigProposal() external onlyOwner;

setPauser

Updates the dedicated emergency pauser.

The owner retains unpause authority and may still pause directly.

function setPauser(
    address newPauser
) external onlyOwner;

pause

Pause deposits into both tranches

function pause() external onlyPauserOrOwner;

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.

This admits previously quarantined excess into canonical pool accounting 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 for protocol-authorized settlement or keeper payments.

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;

recordClaimantInflow

Records claimant-owned value into the tranche claimant path.

Revenue and recapitalization remain distinct economic buckets, but share one API.

function recordClaimantInflow(
    uint256 amount,
    ICfdVault.ClaimantInflowKind kind,
    ICfdVault.ClaimantInflowCashMode cashMode
) 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.

Mints bootstrap shares so 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 override(IHousePool, IPerpsLPActions) 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 override(IHousePool, IPerpsLPActions) onlyVault;

Parameters

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

depositJunior

Deposit USDC into the junior tranche.

function depositJunior(
    uint256 amount
) external override(IHousePool, IPerpsLPActions) 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 override(IHousePool, IPerpsLPActions) 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);

seniorRateBps

function seniorRateBps() public view returns (uint256);

markStalenessLimit

function markStalenessLimit() public view returns (uint256);

seniorFrozenLpFeeBps

function seniorFrozenLpFeeBps() public view returns (uint256);

juniorFrozenLpFeeBps

function juniorFrozenLpFeeBps() public view returns (uint256);

isOracleFrozen

function isOracleFrozen() public view override returns (bool);

frozenLpFeeBps

function frozenLpFeeBps(
    bool isSenior
) public view override returns (uint256);

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(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot
) internal view;

_requireRateChangeMarkFresh

function _requireRateChangeMarkFresh(
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot
) internal view;

_requireBootstrapOracleLive

function _requireBootstrapOracleLive(
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot
) internal pure;

_reconcile

function _reconcile(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot
) internal;

_getWithdrawalSnapshot

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

_buildHousePoolContext

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

_buildCurrentHousePoolContext

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

_previewPendingAccountingState

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

_markIsFreshForReconcile

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

_withdrawalsLive

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

_validatePoolConfig

function _validatePoolConfig(
    PoolConfig memory config
) internal pure;

_checkpointSeniorYieldBeforeRateChange

function _checkpointSeniorYieldBeforeRateChange() internal;

_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(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    uint256 reservedUnassignedAssets,
    bool isProjected
) internal view returns (HousePoolAccountingLib.WithdrawalSnapshot memory snapshot);

_checkpointSeniorYieldBeforePrincipalMutation

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

_applyPendingClaimantBucketsLive

function _applyPendingClaimantBucketsLive(
    HousePoolEngineViewTypes.HousePoolInputSnapshot memory accountingSnapshot,
    HousePoolEngineViewTypes.HousePoolStatusSnapshot memory statusSnapshot
) internal;

_applyPendingClaimantBucketsPreview

function _applyPendingClaimantBucketsPreview(
    PendingAccountingState memory state
) internal view;

_getPendingClaimantBuckets

function _getPendingClaimantBuckets()
    internal
    view
    returns (HousePoolPendingPreviewLib.ClaimantPendingBuckets memory buckets);

_clearPendingClaimantBuckets

function _clearPendingClaimantBuckets() internal;

_recordPendingClaimantInflow

function _recordPendingClaimantInflow(
    ICfdVault.ClaimantInflowKind kind,
    uint256 amount
) internal;

_copyPendingAccountingState

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

_pendingClaimantBucketAssets

function _pendingClaimantBucketAssets() internal view returns (uint256);

_getHousePoolInputSnapshot

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

_getHousePoolStatusSnapshot

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

_getHousePoolSnapshots

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

_requireWithdrawalsLive

function _requireWithdrawalsLive(
    HousePoolEngineViewTypes.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);

PoolConfigProposed

event PoolConfigProposed(
    uint256 seniorRateBps,
    uint256 markStalenessLimit,
    uint256 seniorFrozenLpFeeBps,
    uint256 juniorFrozenLpFeeBps,
    uint256 activationTime
);

PoolConfigFinalized

event PoolConfigFinalized();

FrozenLpFeesUpdated

event FrozenLpFeesUpdated(uint256 seniorFeeBps, uint256 juniorFeeBps);

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);

ClaimantInflowAccounted

event ClaimantInflowAccounted(
    address indexed caller,
    ICfdVault.ClaimantInflowKind kind,
    ICfdVault.ClaimantInflowCashMode cashMode,
    uint256 amountUsdc
);

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();

PauserUpdated

event PauserUpdated(address indexed previousPauser, address indexed newPauser);

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__InvalidFrozenLpFee

error HousePool__InvalidFrozenLpFee();

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();

HousePool__UnauthorizedPauser

error HousePool__UnauthorizedPauser();

HousePool__OracleFrozen

error HousePool__OracleFrozen();

Structs

VaultLiquidityView

struct VaultLiquidityView {
    uint256 totalAssetsUsdc;
    uint256 freeUsdc;
    uint256 withdrawalReservedUsdc;
    uint256 pendingRecapitalizationUsdc;
    uint256 pendingTradingRevenueUsdc;
    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 {
    HousePoolEngineViewTypes.HousePoolInputSnapshot accountingSnapshot;
    HousePoolEngineViewTypes.HousePoolStatusSnapshot statusSnapshot;
    PendingAccountingState pendingState;
}

PoolConfig

struct PoolConfig {
    uint256 seniorRateBps;
    uint256 markStalenessLimit;
    uint256 seniorFrozenLpFeeBps;
    uint256 juniorFrozenLpFeeBps;
}

MarginClearinghouse

Git Source

Inherits: IMarginAccount, Ownable2Step, ReentrancyGuardTransient

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

MARK_PRICE_STALE_SELECTOR

bytes4 internal constant MARK_PRICE_STALE_SELECTOR = bytes4(keccak256("CfdEngine__MarkPriceStale()"));

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;

activeCommittedOrderReservationUsdc

mapping(bytes32 => uint256) internal activeCommittedOrderReservationUsdc;

activeReservationCount

mapping(bytes32 => uint256) internal activeReservationCount;

engine

address public engine;

Functions

onlyOperator

modifier onlyOperator();

onlyOrderRouter

modifier onlyOrderRouter();

onlyEngine

modifier onlyEngine();

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

depositMargin

Trader-facing wrapper that deposits into the caller’s canonical account id.

function depositMargin(
    uint256 amount
) external nonReentrant;

withdraw

Withdraws settlement USDC from a margin account.

function withdraw(
    bytes32 accountId,
    uint256 amount
) external nonReentrant;

Parameters

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

withdrawMargin

Trader-facing wrapper that withdraws from the caller’s canonical account id.

function withdrawMargin(
    uint256 amount
) external nonReentrant;

_deposit

function _deposit(
    bytes32 accountId,
    address owner,
    uint256 amount
) internal;

_withdraw

function _withdraw(
    bytes32 accountId,
    address owner,
    uint256 amount
) internal;

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);

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,
    uint256 amountUsdc
) internal;

lockReservedSettlement

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

unlockReservedSettlement

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

settleUsdc

Adjusts settlement USDC for realized PnL, deferred servicing, and 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);

consumeSettlementLoss

Consumes a realized settlement loss from free settlement first, then from active position margin.

Unrelated locked margin remains protected.

function consumeSettlementLoss(
    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;

_checkpointCarryBeforeMarginChange

function _checkpointCarryBeforeMarginChange(
    bytes32 accountId
) internal;

_checkpointCarryBeforeMarginChange

function _checkpointCarryBeforeMarginChange(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) internal;

_requireNoActiveReservations

function _requireNoActiveReservations(
    bytes32 accountId
) internal view;

_realizeOrCheckpointCarryBeforeMarginChange

function _realizeOrCheckpointCarryBeforeMarginChange(
    bytes32 accountId,
    uint256 reachableCollateralBasisUsdc
) 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;

_activeMarginReservationIds

The router already maintains the active reservation FIFO for each account, so the clearinghouse no longer needs an append-only historical reservation index.

function _activeMarginReservationIds(
    bytes32 accountId
) internal view returns (uint64[] memory reservationIds);

_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)

reserveCloseExecutionBountyFromSettlement

Reserves free settlement for the engine’s fresh close-bounty path with carry checkpointing.

function reserveCloseExecutionBountyFromSettlement(
    bytes32 accountId,
    uint256 amount,
    address recipient
) external onlyEngine;

reserveStaleCloseExecutionBountyFromSettlement

Reserves free settlement for the engine’s stale close-bounty path without checkpointing carry.

function reserveStaleCloseExecutionBountyFromSettlement(
    bytes32 accountId,
    uint256 amount,
    address recipient
) external onlyEngine;

seizePositionMarginUsdc

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

reserveStaleCloseExecutionBountyFromPositionMargin

Reserves active position margin for the engine’s stale close-bounty path without checkpointing carry.

function reserveStaleCloseExecutionBountyFromPositionMargin(
    bytes32 accountId,
    uint256 amount,
    address recipient
) external onlyEngine;

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);

_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__ReservationLedgerActive

error MarginClearinghouse__ReservationLedgerActive();

MarginClearinghouse__EngineAlreadySet

error MarginClearinghouse__EngineAlreadySet();

MarginClearinghouse__ZeroAddress

error MarginClearinghouse__ZeroAddress();

MarginClearinghouse__InsufficientBucketMargin

error MarginClearinghouse__InsufficientBucketMargin();

MarginClearinghouse__AmountOverflow

error MarginClearinghouse__AmountOverflow();

OrderRouter

Git Source

Inherits: IPerpsKeeper, IPerpsTraderActions, IOrderRouterAdminHost, OrderExecutionOrchestrator

Title: OrderRouter (The MEV Shield)

Manages Commit-Reveal, MEV protection, and the un-brickable FIFO queue.

Holds only non-trader-owned keeper execution reserves. Trader collateral remains in MarginClearinghouse.

Note: security-contact: contact@plether.com

Constants

admin

address public immutable admin;

DEFAULT_MAX_ORDER_AGE

uint256 internal constant DEFAULT_MAX_ORDER_AGE = 60;

State Variables

nextCommitId

uint64 public nextCommitId = 1;

nextExecuteId

uint64 public nextExecuteId = 1;

maxOrderAge

uint256 public maxOrderAge;

minOpenNotionalUsdc

uint256 public minOpenNotionalUsdc;

openOrderExecutionBountyBps

uint256 public openOrderExecutionBountyBps;

minOpenOrderExecutionBountyUsdc

uint256 public minOpenOrderExecutionBountyUsdc;

maxOpenOrderExecutionBountyUsdc

uint256 public maxOpenOrderExecutionBountyUsdc;

closeOrderExecutionBountyUsdc

uint256 public closeOrderExecutionBountyUsdc;

maxPendingOrders

uint256 public maxPendingOrders;

globalTailOrderId

uint64 public globalTailOrderId;

Functions

_onlyEngine

function _onlyEngine() internal view;

_onlyAdmin

function _onlyAdmin() internal view;

constructor

constructor(
    address _engine,
    address _engineLens,
    address _vault,
    address _pyth,
    bytes32[] memory _feedIds,
    uint256[] memory _quantities,
    uint256[] memory _basePrices,
    bool[] memory _inversions
) OrderOracleExecution(_engine, _engineLens, _vault, _pyth, _feedIds, _quantities, _basePrices, _inversions);

Parameters

NameTypeDescription
_engineaddressCfdEngine that processes trades and liquidations
_engineLensaddress
_vaultaddressCfdVault used for vault depth queries and liquidation bounty payouts
_pythaddressPyth oracle contract (address(0) enables mock mode on Anvil)
_feedIdsbytes32[]Pyth price feed IDs for each basket component
_quantitiesuint256[]Weight of each component (must sum to 1e18)
_basePricesuint256[]Base price per component for normalization (8 decimals)
_inversionsbool[]Whether to invert each feed (e.g. USD/JPY -> JPY/USD)

_revertZeroAddress

function _revertZeroAddress() internal pure override;

_revertOracleValidation

function _revertOracleValidation(
    uint8 code
) internal pure;

_revertQueueState

function _revertQueueState(
    uint8 code
) internal pure;

_revertCommitValidation

function _revertCommitValidation(
    uint8 code
) internal pure;

_revertEmptyFeeds

function _revertEmptyFeeds() internal pure override;

_revertLengthMismatch

function _revertLengthMismatch() internal pure override;

_revertInvalidBasePrice

function _revertInvalidBasePrice() internal pure override;

_revertInvalidWeights

function _revertInvalidWeights() internal pure override;

_revertMissingPythUpdateData

function _revertMissingPythUpdateData() internal pure override;

_revertInsufficientPythFee

function _revertInsufficientPythFee() internal pure override;

_revertMockModeDisabled

function _revertMockModeDisabled() internal pure override;

_revertOraclePriceTooStale

function _revertOraclePriceTooStale() internal pure override;

_revertOracleConfidenceTooWide

function _revertOracleConfidenceTooWide() internal pure override;

_revertOraclePublishTimeOutOfOrder

function _revertOraclePublishTimeOutOfOrder() internal pure override;

_revertMevOraclePriceTooStale

function _revertMevOraclePriceTooStale() internal pure override;

_revertOraclePriceNegative

function _revertOraclePriceNegative() internal pure override;

commitOrder

Submits a trade intent to the FIFO queue. Margin and the order’s execution bounty are reserved immediately.

function commitOrder(
    CfdTypes.Side side,
    uint256 sizeDelta,
    uint256 marginDelta,
    uint256 targetPrice,
    bool isClose
) external;

Parameters

NameTypeDescription
sideCfdTypes.SideBULL or BEAR
sizeDeltauint256Position size change (18 decimals)
marginDeltauint256Margin to add or remove (6 decimals, USDC)
targetPriceuint256Slippage limit price (8 decimals, 0 = market order)
isCloseboolTrue to allow execution even when paused or in FAD close-only mode

syncMarginQueue

Returns the total queued escrow state for an account across all pending orders.

function syncMarginQueue(
    bytes32 accountId
) external;

getPendingOrderView

function getPendingOrderView(
    uint64 orderId
) external view returns (IOrderRouterAccounting.PendingOrderView memory pending, uint64 nextAccountOrderId);

executeOrder

Keeper executes the current global queue head.

Validates oracle freshness, publish-time ordering, and slippage, then delegates to the engine. Invalid, expired, or out-of-slippage orders are finalized from router-custodied execution bounty escrow; the router does not maintain a retry/requeue lane.

function executeOrder(
    uint64 orderId,
    bytes[] calldata pythUpdateData
) external payable;

Parameters

NameTypeDescription
orderIduint64Must equal the current global queue head (expired orders are auto-skipped)
pythUpdateDatabytes[]Pyth price update blobs; attach ETH to cover the Pyth fee

executeOrderBatch

Executes queued pending orders against a single Pyth price tick. Updates Pyth once, then loops through the FIFO queue. Aggregates reserved USDC execution bounties across processed orders and refunds excess ETH in a single transfer.

function executeOrderBatch(
    uint64 maxOrderId,
    bytes[] calldata pythUpdateData
) external payable;

Parameters

NameTypeDescription
maxOrderIduint64Inclusive upper bound on committed order ids the batch may begin processing from
pythUpdateDatabytes[]Pyth price update blobs; attach ETH to cover the Pyth fee

_queueHeadOrderId

function _queueHeadOrderId() internal view override returns (uint64);

_setQueueHeadOrderId

function _setQueueHeadOrderId(
    uint64 orderId
) internal override;

_queueTailOrderId

function _queueTailOrderId() internal view override returns (uint64);

_setQueueTailOrderId

function _setQueueTailOrderId(
    uint64 orderId
) internal override;

_revertOrderNotPending

function _revertOrderNotPending() internal pure override;

_maxOrderAge

function _maxOrderAge() internal view override returns (uint256);

_revertNoOrdersToExecute

function _revertNoOrdersToExecute() internal pure override;

_revertInsufficientGas

function _revertInsufficientGas() internal pure override;

_revertMevDetected

function _revertMevDetected() internal pure override;

_revertCloseOnlyMode

function _revertCloseOnlyMode() internal pure override;

_sendEth

function _sendEth(
    address to,
    uint256 amount
) internal override;

_creditOrDeferLiquidationBounty

Liquidation keeper value follows the same default custody path as other keeper flows: credit the beneficiary’s clearinghouse account when cash is available, otherwise defer the claim for later clearinghouse settlement.

function _creditOrDeferLiquidationBounty(
    uint256 liquidationBountyUsdc,
    uint256 executionPrice,
    uint64 oraclePublishTime
) internal;

_forfeitEscrowedOrderBountiesOnLiquidation

function _forfeitEscrowedOrderBountiesOnLiquidation(
    bytes32 accountId
) internal;

_clearLiquidatedAccountOrders

function _clearLiquidatedAccountOrders(
    bytes32 accountId
) internal;

_quoteOpenOrderExecutionBountyUsdc

function _quoteOpenOrderExecutionBountyUsdc(
    uint256 sizeDelta,
    uint256 price
) internal view returns (uint256);

_reserveCloseExecutionBounty

function _reserveCloseExecutionBounty(
    bytes32 accountId,
    uint256 sizeDelta,
    uint256 executionBountyUsdc
) internal override;

_hasFreshCarryCheckpointMark

function _hasFreshCarryCheckpointMark() internal view returns (bool);

_deleteOrder

function _deleteOrder(
    uint64 orderId,
    IOrderRouterAccounting.OrderStatus terminalStatus
) internal override;

applyRouterConfig

function applyRouterConfig(
    IOrderRouterAdminHost.RouterConfig calldata config
) external;

applyOracleConfig

function applyOracleConfig(
    IOrderRouterAdminHost.OracleConfig calldata config
) external;

_nextCommitId

function _nextCommitId() internal view override returns (uint64);

_releaseCommittedMarginForExecution

function _releaseCommittedMarginForExecution(
    uint64 orderId
) internal override;

updateMarkPrice

Push a fresh mark price to the engine without processing an order. Required before LP deposits/withdrawals when mark is stale.

function updateMarkPrice(
    bytes[] calldata pythUpdateData
) external payable;

Parameters

NameTypeDescription
pythUpdateDatabytes[]Pyth price update blobs; attach ETH to cover the Pyth fee

executeLiquidation

Keeper-triggered liquidation using the canonical live-market staleness policy. Forfeits any queued-order execution escrow to the vault instead of crediting it back to trader settlement, then credits the liquidation keeper through the clearinghouse when cash is available.

function executeLiquidation(
    bytes32 accountId,
    bytes[] calldata pythUpdateData
) external payable;

Parameters

NameTypeDescription
accountIdbytes32The account to liquidate (bytes32-encoded address)
pythUpdateDatabytes[]Pyth price update blobs; attach ETH to cover the Pyth fee

_revertInsufficientFreeEquity

function _revertInsufficientFreeEquity() internal pure override;

_revertMarginOrderLinkCorrupted

function _revertMarginOrderLinkCorrupted() internal pure override;

_revertPendingOrderLinkCorrupted

function _revertPendingOrderLinkCorrupted() internal pure override;

Events

OrderCommitted

event OrderCommitted(uint64 indexed orderId, bytes32 indexed accountId, CfdTypes.Side side);

Errors

OrderRouter__ZeroSize

error OrderRouter__ZeroSize();

OrderRouter__OracleValidation

error OrderRouter__OracleValidation(uint8 code);

OrderRouter__QueueState

error OrderRouter__QueueState(uint8 code);

OrderRouter__CommitValidation

error OrderRouter__CommitValidation(uint8 code);

OrderRouter__InsufficientGas

error OrderRouter__InsufficientGas();

OrderRouter__PredictableOpenInvalid

error OrderRouter__PredictableOpenInvalid(uint8 code);

OrderRouterAdmin

Git Source

Inherits: Ownable, Pausable

Constants

TIMELOCK_DELAY

uint256 public constant TIMELOCK_DELAY = 48 hours;

MAX_PENDING_ORDERS_LIMIT

uint256 internal constant MAX_PENDING_ORDERS_LIMIT = 32;

MAX_CLOSE_ORDER_EXECUTION_BOUNTY_USDC

uint256 internal constant MAX_CLOSE_ORDER_EXECUTION_BOUNTY_USDC = 1_000_000;

MIN_ENGINE_GAS_FLOOR

uint256 internal constant MIN_ENGINE_GAS_FLOOR = 100_000;

MIN_ENGINE_GAS_CAP

uint256 internal constant MIN_ENGINE_GAS_CAP = 5_000_000;

MAX_PRUNE_ORDERS_PER_CALL_LIMIT

uint256 internal constant MAX_PRUNE_ORDERS_PER_CALL_LIMIT = 256;

MAX_ORDER_AGE_LIMIT

uint256 internal constant MAX_ORDER_AGE_LIMIT = 1 hours;

router

IOrderRouterAdminHost public immutable router;

State Variables

claimableEth

mapping(address => uint256) public claimableEth;

pauser

address public pauser;

pendingRouterConfig

IOrderRouterAdminHost.RouterConfig public pendingRouterConfig;

routerConfigActivationTime

uint256 public routerConfigActivationTime;

_pendingOracleConfig

IOrderRouterAdminHost.OracleConfig private _pendingOracleConfig;

oracleConfigActivationTime

uint256 public oracleConfigActivationTime;

Functions

constructor

constructor(
    address router_,
    address initialOwner
) Ownable(initialOwner);

onlyRouterHost

modifier onlyRouterHost();

onlyPauserOrOwner

modifier onlyPauserOrOwner();

proposeRouterConfig

function proposeRouterConfig(
    IOrderRouterAdminHost.RouterConfig calldata config
) external onlyOwner;

finalizeRouterConfig

function finalizeRouterConfig() external onlyOwner;

cancelRouterConfig

function cancelRouterConfig() external onlyOwner;

proposeOracleConfig

function proposeOracleConfig(
    IOrderRouterAdminHost.OracleConfig calldata config
) external onlyOwner;

finalizeOracleConfig

function finalizeOracleConfig() external onlyOwner;

cancelOracleConfig

function cancelOracleConfig() external onlyOwner;

getPendingOracleConfig

function getPendingOracleConfig() external view returns (IOrderRouterAdminHost.OracleConfig memory config);

setPauser

function setPauser(
    address newPauser
) external onlyOwner;

pause

function pause() external onlyPauserOrOwner;

unpause

function unpause() external onlyOwner;

creditClaimableEth

function creditClaimableEth(
    address beneficiary,
    uint256 amount
) external payable onlyRouterHost;

claimBalance

function claimBalance(
    bool ethBalance
) external;

_requireTimelockReady

function _requireTimelockReady(
    uint256 activationTime
) internal view;

_validateRouterConfig

function _validateRouterConfig(
    IOrderRouterAdminHost.RouterConfig memory config
) internal pure;

_validateOracleConfig

function _validateOracleConfig(
    IOrderRouterAdminHost.OracleConfig calldata config
) internal pure;

Events

RouterConfigProposed

event RouterConfigProposed(IOrderRouterAdminHost.RouterConfig config, uint256 activationTime);

RouterConfigFinalized

event RouterConfigFinalized(IOrderRouterAdminHost.RouterConfig config);

RouterConfigCancelled

event RouterConfigCancelled();

OracleConfigProposed

event OracleConfigProposed(IOrderRouterAdminHost.OracleConfig config, uint256 activationTime);

OracleConfigFinalized

event OracleConfigFinalized(IOrderRouterAdminHost.OracleConfig config);

OracleConfigCancelled

event OracleConfigCancelled();

PauserUpdated

event PauserUpdated(address indexed previousPauser, address indexed newPauser);

Errors

OrderRouterAdmin__TimelockNotReady

error OrderRouterAdmin__TimelockNotReady();

OrderRouterAdmin__NoProposal

error OrderRouterAdmin__NoProposal();

OrderRouterAdmin__InvalidMaxOrderAge

error OrderRouterAdmin__InvalidMaxOrderAge();

OrderRouterAdmin__InvalidStalenessLimit

error OrderRouterAdmin__InvalidStalenessLimit();

OrderRouterAdmin__InvalidConfidenceRatio

error OrderRouterAdmin__InvalidConfidenceRatio();

OrderRouterAdmin__InvalidExecutionBounty

error OrderRouterAdmin__InvalidExecutionBounty();

OrderRouterAdmin__InvalidPendingOrderLimit

error OrderRouterAdmin__InvalidPendingOrderLimit();

OrderRouterAdmin__InvalidGasLimit

error OrderRouterAdmin__InvalidGasLimit();

OrderRouterAdmin__InvalidOracleConfig

error OrderRouterAdmin__InvalidOracleConfig();

OrderRouterAdmin__Unauthorized

error OrderRouterAdmin__Unauthorized();

OrderRouterAdmin__UnauthorizedPauser

error OrderRouterAdmin__UnauthorizedPauser();

OrderRouterAdmin__NothingToClaim

error OrderRouterAdmin__NothingToClaim();

OrderRouterAdmin__EthTransferFailed

error OrderRouterAdmin__EthTransferFailed();

OrderRouterAdmin__EthAmountMismatch

error OrderRouterAdmin__EthAmountMismatch();

PerpsPublicLens

Git Source

Inherits: IPerpsTraderViews, IPerpsLPViews, IProtocolViews

Title: PerpsPublicLens

Compact read facade for the simplified product-facing perps surface.

This intentionally presents a narrower, easier-to-consume view than the rich engine and accounting lenses used by tests, audits, and operator tooling.

Constants

ACCOUNT_LENS

ICfdEngineAccountLens public immutable ACCOUNT_LENS;

ENGINE

ICfdEngineCore public immutable ENGINE;

ORDER_ROUTER

IOrderRouterAccounting public immutable ORDER_ROUTER;

HOUSE_POOL

HousePool public immutable HOUSE_POOL;

Functions

constructor

constructor(
    address accountLens_,
    address engine_,
    address orderRouter_,
    address housePool_
);

Parameters

NameTypeDescription
accountLens_addressRich account lens used to derive compact trader views.
engine_addressCore engine used for runtime status and risk params.
orderRouter_addressRouter accounting surface used for pending-order summaries.
housePool_addressHousePool used for tranche and protocol status views.

getTraderAccount

Returns the compact trader account summary for a canonical perps account.

function getTraderAccount(
    bytes32 accountId
) external view returns (PerpsViewTypes.TraderAccountView memory viewData);

getPosition

Returns the compact current-position view for an account.

function getPosition(
    bytes32 accountId
) external view returns (PerpsViewTypes.PositionView memory viewData);

getPendingOrders

Returns all currently pending orders for an account.

The public surface only returns pending orders because executed and failed orders are not part of the compact product-facing queue summary.

function getPendingOrders(
    bytes32 accountId
) external view returns (PerpsViewTypes.PendingOrderView[] memory pending);

isLiquidatable

Returns whether the account’s current live position is liquidatable.

function isLiquidatable(
    bytes32 accountId
) external view returns (bool);

getSeniorTranche

Returns the compact senior tranche view.

function getSeniorTranche() external view returns (PerpsViewTypes.TrancheView memory viewData);

getJuniorTranche

Returns the compact junior tranche view.

function getJuniorTranche() external view returns (PerpsViewTypes.TrancheView memory viewData);

getLpStatus

Returns high-level LP status flags.

function getLpStatus() external view returns (PerpsViewTypes.LpStatusView memory viewData);

getProtocolStatus

Returns high-level protocol runtime status flags.

function getProtocolStatus() external view returns (PerpsViewTypes.ProtocolStatusView memory viewData);

_getPositionView

function _getPositionView(
    bytes32 accountId
) internal view returns (PerpsViewTypes.PositionView memory viewData);

_getTrancheView

function _getTrancheView(
    address vault,
    bool isSenior
) internal view returns (PerpsViewTypes.TrancheView memory viewData);

_getProtocolStatusView

function _getProtocolStatusView() internal view returns (PerpsViewTypes.ProtocolStatusView memory viewData);

TrancheVault

Git Source

Inherits: ERC4626

Title: TrancheVault

ERC4626 share token for a HousePool tranche (senior or junior). Routes all deposits/withdrawals through HousePool.

Note: security-contact: contact@plether.com

Constants

POOL

IHousePool public immutable POOL;

IS_SENIOR

bool public immutable IS_SENIOR;

DEPOSIT_COOLDOWN

uint256 public constant DEPOSIT_COOLDOWN = 1 hours;

State Variables

lastDepositTime

mapping(address => uint256) public lastDepositTime;

seedReceiver

address public seedReceiver;

seedShareFloor

uint256 public seedShareFloor;

Functions

constructor

constructor(
    IERC20 _usdc,
    address _pool,
    bool _isSenior,
    string memory _name,
    string memory _symbol
) ERC4626(_usdc) ERC20(_name, _symbol);

Parameters

NameTypeDescription
_usdcIERC20Underlying USDC token used as the vault asset
_pooladdressHousePool that holds USDC and manages the tranche waterfall
_isSeniorboolTrue for the senior tranche, false for junior
_namestringERC20 share token name
_symbolstringERC20 share token symbol

_decimalsOffset

Virtual share offset mitigates ERC4626 first-depositor inflation attack

function _decimalsOffset() internal pure override returns (uint8);

_update

Enforces a deposit cooldown on share transfers. Prevents flash-deposit-then-transfer to bypass the withdrawal cooldown. Propagates the sender’s cooldown to the receiver if it is more recent.

function _update(
    address from,
    address to,
    uint256 amount
) internal override;

totalAssets

Returns the tranche assets from the pending post-reconcile HousePool state.

function totalAssets() public view override returns (uint256);

deposit

Deposits assets into the tranche after reconciling pool accounting and lifecycle gates.

function deposit(
    uint256 assets,
    address receiver
) public override returns (uint256);

mint

Mints tranche shares after reconciling pool accounting and lifecycle gates.

function mint(
    uint256 shares,
    address receiver
) public override returns (uint256);

previewDeposit

function previewDeposit(
    uint256 assets
) public view override returns (uint256);

previewMint

function previewMint(
    uint256 shares
) public view override returns (uint256);

maxDeposit

Returns the current max deposit if lifecycle, freshness, and impairment gates allow deposits.

function maxDeposit(
    address receiver
) public view override returns (uint256);

maxMint

Returns the current max mint if lifecycle, freshness, and impairment gates allow deposits.

function maxMint(
    address receiver
) public view override returns (uint256);

withdraw

Withdraws tranche assets after reconciling pool accounting.

function withdraw(
    uint256 assets,
    address receiver,
    address _owner
) public override returns (uint256);

redeem

Redeems tranche shares after reconciling pool accounting.

function redeem(
    uint256 shares,
    address receiver,
    address _owner
) public override returns (uint256);

previewWithdraw

function previewWithdraw(
    uint256 assets
) public view override returns (uint256);

previewRedeem

function previewRedeem(
    uint256 shares
) public view override returns (uint256);

maxWithdraw

Returns the withdrawable asset amount after cooldown and pool-level withdrawal gates.

function maxWithdraw(
    address _owner
) public view override returns (uint256);

maxRedeem

Returns the redeemable share amount after cooldown and pool-level withdrawal gates.

function maxRedeem(
    address _owner
) public view override returns (uint256);

_deposit

function _deposit(
    address caller,
    address receiver,
    uint256 assets,
    uint256 shares
) internal override;

_withdraw

function _withdraw(
    address caller,
    address receiver,
    address _owner,
    uint256 assets,
    uint256 shares
) internal override;

bootstrapMint

Mints shares to explicitly bootstrap previously quarantined pool assets into this tranche.

Only the pool may call this. The pool must have already assigned matching assets to the tranche principal.

function bootstrapMint(
    uint256 shares,
    address receiver
) external;

configureSeedPosition

Registers or increases the permanent seed-share floor for this tranche.

The pool must mint the corresponding shares before or within the same flow.

function configureSeedPosition(
    address receiver,
    uint256 floorShares
) external;

_unlockedOwnerShares

function _unlockedOwnerShares(
    address _owner
) internal view returns (uint256 ownerShares);

_isTerminallyWiped

function _isTerminallyWiped() internal view returns (bool);

_requireActiveTranche

function _requireActiveTranche() internal view;

_requireLifecycleActiveForOrdinaryDeposit

function _requireLifecycleActiveForOrdinaryDeposit() internal view;

_ordinaryDepositsAllowed

function _ordinaryDepositsAllowed() internal view returns (bool);

_canDepositNow

function _canDepositNow() internal view returns (bool);

_frozenLpFeeBps

function _frozenLpFeeBps() internal view returns (uint256);

_applyFee

function _applyFee(
    uint256 grossAssets,
    uint256 feeBps
) internal pure returns (uint256);

_grossUpForFee

function _grossUpForFee(
    uint256 netAssets,
    uint256 feeBps
) internal pure returns (uint256);

_applyFeeToShares

function _applyFeeToShares(
    uint256 grossShares,
    uint256 feeBps
) internal pure returns (uint256);

_grossUpSharesForFee

function _grossUpSharesForFee(
    uint256 netShares,
    uint256 feeBps
) internal pure returns (uint256);

_previewFrozenDepositShares

function _previewFrozenDepositShares(
    uint256 assets,
    uint256 feeBps
) internal view returns (uint256);

_previewFrozenMintAssets

function _previewFrozenMintAssets(
    uint256 shares,
    uint256 feeBps
) internal view returns (uint256);

_maxFrozenMintShares

function _maxFrozenMintShares(
    uint256 feeBps
) internal view returns (uint256);

Errors

TrancheVault__DepositCooldown

error TrancheVault__DepositCooldown();

TrancheVault__TransferDuringCooldown

error TrancheVault__TransferDuringCooldown();

TrancheVault__TrancheImpaired

error TrancheVault__TrancheImpaired();

TrancheVault__ThirdPartyDepositForExistingHolder

error TrancheVault__ThirdPartyDepositForExistingHolder();

TrancheVault__NotPool

error TrancheVault__NotPool();

TrancheVault__SeedFloorBreached

error TrancheVault__SeedFloorBreached();

TrancheVault__InvalidSeedPosition

error TrancheVault__InvalidSeedPosition();

TrancheVault__TerminallyWiped

error TrancheVault__TerminallyWiped();

TrancheVault__TradingNotActive

error TrancheVault__TradingNotActive();

BullLeverageRouter

Git Source

Inherits: LeverageRouterBase

Title: BullLeverageRouter

Leverage router for plDXY-BULL positions via Morpho Blue.

Uses Morpho flash loans + Splitter minting to acquire plDXY-BULL, then deposits as Morpho collateral. Close operation uses a single plDXY-BEAR flash mint for simplicity and gas efficiency. Uses Morpho’s fee-free flash loans for capital efficiency.

STATE MACHINE - OPEN LEVERAGE: ┌─────────────────────────────────────────────────────────────────────────┐ │ openLeverage(principal, leverage) │ │ 1. Pull USDC from user │ │ 2. Flash loan additional USDC from Morpho (fee-free) │ │ └──► onMorphoFlashLoan(OP_OPEN) │ │ └──► _executeOpen() │ │ 1. Mint plDXY-BEAR + plDXY-BULL pairs via Splitter │ │ 2. Sell plDXY-BEAR on Curve → USDC │ │ 3. Stake plDXY-BULL → splDXY-BULL │ │ 4. Deposit splDXY-BULL to Morpho (user’s collateral) │ │ 5. Borrow USDC from Morpho to cover flash repayment │ │ 6. Emit LeverageOpened event │ └─────────────────────────────────────────────────────────────────────────┘

STATE MACHINE - CLOSE LEVERAGE (Single Flash Mint): ┌─────────────────────────────────────────────────────────────────────────┐ │ closeLeverage(debtToRepay, collateralToWithdraw) │ │ 1. Flash mint plDXY-BEAR (collateral + extra for debt repayment) │ │ └──► onFlashLoan(OP_CLOSE) │ │ └──► _executeClose() │ │ 1. Sell extra plDXY-BEAR on Curve → USDC │ │ 2. Repay user’s Morpho debt with USDC from sale │ │ 3. Withdraw user’s splDXY-BULL from Morpho │ │ 4. Unstake splDXY-BULL → plDXY-BULL │ │ 5. Redeem plDXY-BEAR + plDXY-BULL → USDC │ │ 6. Buy plDXY-BEAR on Curve to repay flash mint │ │ 7. Transfer remaining USDC to user │ │ 8. Emit LeverageClosed event │ └─────────────────────────────────────────────────────────────────────────┘

STATE MACHINE - ADD COLLATERAL (Morpho Flash Loan): ┌─────────────────────────────────────────────────────────────────────────┐ │ addCollateral(usdcAmount) │ │ 1. Pull USDC from user │ │ 2. Flash loan USDC from Morpho (F = U × bearPrice / bullPrice) │ │ └──► onMorphoFlashLoan(OP_ADD_COLLATERAL) │ │ └──► _executeAddCollateral() │ │ 1. Mint plDXY-BEAR + plDXY-BULL pairs via Splitter │ │ 2. Sell ALL plDXY-BEAR on Curve → USDC │ │ 3. Stake plDXY-BULL → splDXY-BULL │ │ 4. Deposit splDXY-BULL to Morpho (user’s collateral) │ │ 5. Repay flash loan from BEAR sale proceeds │ │ 6. Emit CollateralAdded event │ └─────────────────────────────────────────────────────────────────────────┘

Note: security-contact: contact@plether.com

Constants

SPLITTER

SyntheticSplitter for minting/burning token pairs.

ISyntheticSplitter public immutable SPLITTER;

PLDXY_BULL

plDXY-BULL token (collateral for bull positions).

IERC20 public immutable PLDXY_BULL;

STAKED_PLDXY_BULL

StakedToken vault for plDXY-BULL (used as Morpho collateral).

IERC4626 public immutable STAKED_PLDXY_BULL;

CAP

Protocol CAP price (8 decimals, oracle format).

uint256 public immutable CAP;

ORACLE

Oracle for plDXY basket price (returns BEAR price in 8 decimals).

AggregatorV3Interface public immutable ORACLE;

SEQUENCER_UPTIME_FEED

Chainlink L2 sequencer uptime feed (address(0) on L1).

AggregatorV3Interface public immutable SEQUENCER_UPTIME_FEED;

ORACLE_TIMEOUT

Maximum age for a valid oracle price.

uint256 public constant ORACLE_TIMEOUT = 24 hours;

SEQUENCER_GRACE_PERIOD

Grace period after L2 sequencer restarts before accepting prices.

uint256 public constant SEQUENCER_GRACE_PERIOD = 1 hours;

OP_REMOVE_COLLATERAL

Operation type: remove collateral (flash mint).

uint8 internal constant OP_REMOVE_COLLATERAL = 3;

OP_ADD_COLLATERAL

Operation type: add collateral (Morpho flash loan).

uint8 internal constant OP_ADD_COLLATERAL = 4;

Functions

constructor

Deploys BullLeverageRouter with Morpho market configuration.

constructor(
    address _morpho,
    address _splitter,
    address _curvePool,
    address _usdc,
    address _plDxyBear,
    address _plDxyBull,
    address _stakedPlDxyBull,
    MarketParams memory _marketParams,
    address _sequencerUptimeFeed
) LeverageRouterBase(_morpho, _curvePool, _usdc, _plDxyBear);

Parameters

NameTypeDescription
_morphoaddressMorpho Blue protocol address.
_splitteraddressSyntheticSplitter contract address.
_curvePooladdressCurve USDC/plDXY-BEAR pool address.
_usdcaddressUSDC token address.
_plDxyBearaddressplDXY-BEAR token address.
_plDxyBulladdressplDXY-BULL token address.
_stakedPlDxyBulladdresssplDXY-BULL staking vault address.
_marketParamsMarketParamsMorpho market parameters for splDXY-BULL/USDC.
_sequencerUptimeFeedaddressChainlink L2 sequencer feed (address(0) on L1/testnet).

openLeverage

Open a Leveraged plDXY-BULL Position in one transaction.

Mints pairs via Splitter, sells plDXY-BEAR on Curve, deposits plDXY-BULL to Morpho. Uses fixed debt model (same as BEAR router) - Morpho debt equals principal * (leverage - 1).

function openLeverage(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
principaluint256Amount of USDC user sends.
leverageuint256Multiplier (e.g. 3x = 3e18).
maxSlippageBpsuint256Maximum slippage tolerance in basis points (e.g., 50 = 0.5%). Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

openLeverageWithPermit

Open a leveraged plDXY-BULL position with a USDC permit signature (gasless approval).

function openLeverageWithPermit(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
principaluint256Amount of USDC user sends.
leverageuint256Multiplier (e.g. 3x = 3e18).
maxSlippageBpsuint256Maximum slippage tolerance in basis points.
minAmountOutuint256
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_openLeverageCore

function _openLeverageCore(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) internal;

closeLeverage

Close a Leveraged plDXY-BULL Position in one transaction.

Uses a single plDXY-BEAR flash mint to unwind positions efficiently. Queries actual debt from Morpho to ensure full repayment even if interest accrued.

function closeLeverage(
    uint256 collateralToWithdraw,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BULL shares to withdraw from Morpho. NOTE: This is staked token shares, not underlying plDXY-BULL amount. Use STAKED_PLDXY_BULL.previewRedeem() to convert shares to underlying.
maxSlippageBpsuint256Maximum slippage tolerance in basis points. Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

addCollateral

Add collateral to an existing leveraged position.

Uses Morpho flash loan so user’s USDC input ≈ collateral value added. Flow: Flash loan USDC → Mint pairs → Sell ALL BEAR to repay flash loan → Keep BULL as collateral. Formula: flashLoan = userUSDC × bearPrice / bullPrice

function addCollateral(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC representing desired collateral value.
maxSlippageBpsuint256Maximum slippage tolerance in basis points. Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

addCollateralWithPermit

Add collateral with a USDC permit signature (gasless approval).

function addCollateralWithPermit(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC representing desired collateral value.
maxSlippageBpsuint256Maximum slippage tolerance in basis points.
minAmountOutuint256
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_addCollateralCore

function _addCollateralCore(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) internal;

removeCollateral

Remove collateral from an existing leveraged position.

Uses flash mint of BEAR to redeem pairs, then buys back BEAR with USDC. Reverts if the resulting position would be unhealthy.

function removeCollateral(
    uint256 collateralToWithdraw,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BULL shares to withdraw. NOTE: This is staked token shares, not underlying plDXY-BULL amount.
maxSlippageBpsuint256Maximum slippage tolerance in basis points. Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

onMorphoFlashLoan

Morpho flash loan callback for USDC flash loans (OP_OPEN, OP_ADD_COLLATERAL).

function onMorphoFlashLoan(
    uint256 amount,
    bytes calldata data
) external override;

Parameters

NameTypeDescription
amountuint256Amount of USDC borrowed.
databytesEncoded operation parameters.

onFlashLoan

ERC-3156 flash loan callback for plDXY-BEAR flash mints.

function onFlashLoan(
    address initiator,
    address,
    uint256 amount,
    uint256 fee,
    bytes calldata data
) external override returns (bytes32);

Parameters

NameTypeDescription
initiatoraddressAddress that initiated the flash loan (must be this contract).
<none>address
amountuint256Amount of plDXY-BEAR borrowed.
feeuint256Flash loan fee (always 0 for SyntheticToken).
databytesEncoded operation parameters.

Returns

NameTypeDescription
<none>bytes32CALLBACK_SUCCESS on successful execution.

_executeOpen

Executes open leverage operation within Morpho flash loan callback.

function _executeOpen(
    uint256 loanAmount,
    bytes calldata data
) private;

Parameters

NameTypeDescription
loanAmountuint256Amount of USDC borrowed from Morpho.
databytesEncoded parameters (op, user, deadline, principal, leverage, targetDebt, maxSlippageBps, minSwapOut, minAmountOut).

_executeAddCollateral

Executes add collateral operation within Morpho flash loan callback.

function _executeAddCollateral(
    uint256 flashLoanAmount,
    bytes calldata data
) private;

Parameters

NameTypeDescription
flashLoanAmountuint256Amount of USDC flash loaned.
databytesEncoded parameters (op, user, deadline, usdcAmount, maxSlippageBps, minSwapOut, minAmountOut).

_executeClose

Executes close leverage operation within plDXY-BEAR flash mint callback.

function _executeClose(
    uint256 flashAmount,
    uint256 flashFee,
    bytes calldata data
) private;

Parameters

NameTypeDescription
flashAmountuint256Amount of plDXY-BEAR flash minted.
flashFeeuint256Flash mint fee (always 0).
databytesEncoded parameters (op, user, deadline, collateralToWithdraw, debtToRepay, borrowShares, extraBearForDebt, maxSlippageBps, minAmountOut).

_executeRemoveCollateral

Executes remove collateral operation within plDXY-BEAR flash mint callback.

function _executeRemoveCollateral(
    uint256 flashAmount,
    uint256 flashFee,
    bytes calldata data
) private;

Parameters

NameTypeDescription
flashAmountuint256Amount of plDXY-BEAR flash minted.
flashFeeuint256Flash mint fee (always 0).
databytesEncoded parameters (op, user, deadline, collateralToWithdraw, maxSlippageBps, minAmountOut).

previewOpenLeverage

Preview the result of opening a leveraged plDXY-BULL position.

BULL leverage requires a larger flash loan than BEAR because minting happens at CAP price, not market price. The flash loan is repaid by: bearSaleProceeds + morphoBorrow. Morpho debt still follows the fixed model: principal * (leverage - 1).

function previewOpenLeverage(
    uint256 principal,
    uint256 leverage
) external view returns (uint256 loanAmount, uint256 totalUSDC, uint256 expectedPlDxyBull, uint256 expectedDebt);

Parameters

NameTypeDescription
principaluint256Amount of USDC user will send.
leverageuint256Multiplier (e.g. 2x = 2e18).

Returns

NameTypeDescription
loanAmountuint256Amount of USDC to flash loan.
totalUSDCuint256Total USDC for minting pairs (principal + loan).
expectedPlDxyBulluint256Expected plDXY-BULL tokens received.
expectedDebtuint256Expected Morpho debt (fixed: principal * (leverage - 1)).

previewCloseLeverage

Preview the result of closing a leveraged plDXY-BULL position.

function previewCloseLeverage(
    uint256 debtToRepay,
    uint256 collateralToWithdraw
) external view returns (uint256 expectedUSDC, uint256 usdcForBearBuyback, uint256 expectedReturn);

Parameters

NameTypeDescription
debtToRepayuint256Amount of USDC debt to repay.
collateralToWithdrawuint256Amount of plDXY-BULL collateral to withdraw.

Returns

NameTypeDescription
expectedUSDCuint256Expected USDC from redeeming pairs.
usdcForBearBuybackuint256Expected USDC needed to buy back plDXY-BEAR.
expectedReturnuint256Expected USDC returned to user after all repayments.

previewAddCollateral

Preview the result of adding collateral.

Uses flash loan so user’s USDC input ≈ collateral value added.

function previewAddCollateral(
    uint256 usdcAmount
)
    external
    view
    returns (uint256 flashLoanAmount, uint256 totalUSDC, uint256 expectedPlDxyBull, uint256 expectedStakedShares);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC representing desired collateral value.

Returns

NameTypeDescription
flashLoanAmountuint256Amount of USDC to flash loan.
totalUSDCuint256Total USDC for minting pairs.
expectedPlDxyBulluint256Expected plDXY-BULL tokens to receive.
expectedStakedSharesuint256Expected splDXY-BULL shares to receive.

previewRemoveCollateral

Preview the result of removing collateral.

function previewRemoveCollateral(
    uint256 collateralToWithdraw
)
    external
    view
    returns (
        uint256 expectedPlDxyBull,
        uint256 expectedUsdcFromBurn,
        uint256 usdcForBearBuyback,
        uint256 expectedReturn
    );

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BULL shares to withdraw.

Returns

NameTypeDescription
expectedPlDxyBulluint256Expected plDXY-BULL from unstaking.
expectedUsdcFromBurnuint256Expected USDC from burning pairs.
usdcForBearBuybackuint256Expected USDC needed to buy back flash-minted BEAR.
expectedReturnuint256Expected USDC returned to user.

_calculateOpenParams

Calculates parameters for opening a leveraged position.

function _calculateOpenParams(
    uint256 principal,
    uint256 leverage
) private view returns (OpenParams memory params);

_getValidatedOraclePrice

Returns validated oracle prices with staleness, sequencer, and CAP checks.

function _getValidatedOraclePrice() private view returns (uint256 bearPrice, uint256 bullPrice);

_estimateBearForUsdcSale

Estimates BEAR needed to sell for a target USDC amount using binary search on Curve.

function _estimateBearForUsdcSale(
    uint256 targetUsdc
) private view returns (uint256);

_estimateUsdcForBearBuyback

Estimates USDC needed to buy BEAR using binary search on Curve.

function _estimateUsdcForBearBuyback(
    uint256 bearAmount
) private view returns (uint256);

_binarySearchCurve

Binary search for minimum input to Curve such that get_dy(i, j, input) >= targetOut.

function _binarySearchCurve(
    uint256 i,
    uint256 j,
    uint256 oneUnit,
    uint256 targetOut
) private view returns (uint256);

Parameters

NameTypeDescription
iuint256Curve pool input index.
juint256Curve pool output index.
oneUnituint256One unit of the input token (1e18 for BEAR, 1e6 for USDC).
targetOutuint256Desired minimum output from the swap.

Returns

NameTypeDescription
<none>uint256Minimum input amount that produces at least targetOut.

Events

LeverageOpened

Emitted when a leveraged plDXY-BULL position is opened.

event LeverageOpened(
    address indexed user,
    uint256 principal,
    uint256 leverage,
    uint256 loanAmount,
    uint256 plDxyBullReceived,
    uint256 debtIncurred,
    uint256 maxSlippageBps
);

LeverageClosed

Emitted when a leveraged plDXY-BULL position is closed.

event LeverageClosed(
    address indexed user,
    uint256 debtRepaid,
    uint256 collateralWithdrawn,
    uint256 usdcReturned,
    uint256 maxSlippageBps
);

CollateralAdded

Emitted when collateral is added to a position.

Net USDC cost = usdcAmount - usdcReturned (BEAR sale proceeds returned to user).

event CollateralAdded(
    address indexed user, uint256 usdcAmount, uint256 usdcReturned, uint256 collateralAdded, uint256 maxSlippageBps
);

CollateralRemoved

Emitted when collateral is removed from a position.

event CollateralRemoved(
    address indexed user, uint256 collateralWithdrawn, uint256 usdcReturned, uint256 maxSlippageBps
);

Structs

OpenParams

struct OpenParams {
    uint256 targetDebt;
    uint256 loanAmount;
    uint256 tokensToMint;
    uint256 expectedBearSale;
}

InvarCoin

Git Source

Inherits: ERC20, ERC20Permit, Ownable2Step, Pausable, ReentrancyGuard

Title: InvarCoin (INVAR)

Global purchasing power token backed 50/50 by USDC + plDXY-BEAR via Curve LP.

INVAR is a vault token whose backing is held as Curve USDC/plDXY-BEAR LP tokens. Users deposit USDC, which is single-sided deployed to Curve. The vault earns Curve trading fee yield (virtual price growth), which is harvested and donated to sINVAR stakers. LP tokens are valued with dual pricing to prevent manipulation:

  • totalAssets() and harvest use pessimistic pricing (min of EMA, oracle) for conservative NAV.
  • totalAssetsValidated() provides strict oracle-validated NAV (reverts on stale/invalid oracle).
  • deposit() uses optimistic NAV (max of EMA, oracle) so new depositors cannot dilute existing holders.
  • lpDeposit() values minted LP pessimistically so depositors cannot extract value from stale-high EMA.
  • withdraw() and lpWithdraw() use pro-rata asset distribution (no NAV pricing needed). The oracle-derived LP price mirrors the twocrypto-ng formula: 2 * virtualPrice * sqrt(bearPrice). A 2% USDC buffer (BUFFER_TARGET_BPS) is maintained locally for gas-efficient withdrawals. Permissionless solvers can rebalance USDC/Curve LP inventory against conservative reserve prices. Virtual shares (1e18 INVAR / 1e6 USDC) protect against inflation attacks on the first deposit.

Note: security-contact: contact@plether.com

Constants

USDC

USDC collateral token (6 decimals).

IERC20 public immutable USDC;

BEAR

plDXY-BEAR synthetic token (18 decimals).

IERC20 public immutable BEAR;

CURVE_LP_TOKEN

Curve USDC/plDXY-BEAR LP token.

IERC20 public immutable CURVE_LP_TOKEN;

CURVE_POOL

Curve twocrypto-ng pool for USDC/plDXY-BEAR.

ICurveTwocrypto public immutable CURVE_POOL;

BASKET_ORACLE

Chainlink BasketOracle — weighted basket of 6 FX feeds, returns foreign currencies priced in USD (8 decimals).

AggregatorV3Interface public immutable BASKET_ORACLE;

SEQUENCER_UPTIME_FEED

L2 sequencer uptime feed for staleness protection (address(0) on L1).

AggregatorV3Interface public immutable SEQUENCER_UPTIME_FEED;

CRV_MINTER

Curve Minter for CRV emissions on L1 (address(0) on L2 where claim_rewards handles CRV).

ICurveMinter public immutable CRV_MINTER;

BUFFER_TARGET_BPS

uint256 public constant BUFFER_TARGET_BPS = 200;

DEPLOY_THRESHOLD

uint256 public constant DEPLOY_THRESHOLD = 1000e6;

MAX_SPOT_DEVIATION_BPS

uint256 public constant MAX_SPOT_DEVIATION_BPS = 50;

SOLVER_PRICE_SPREAD_BPS

uint256 private constant SOLVER_PRICE_SPREAD_BPS = 10;

ORACLE_TIMEOUT

uint256 public constant ORACLE_TIMEOUT = 24 hours;

SEQUENCER_GRACE_PERIOD

uint256 public constant SEQUENCER_GRACE_PERIOD = 1 hours;

VIRTUAL_SHARES

uint256 public constant VIRTUAL_SHARES = 1e18;

VIRTUAL_ASSETS

uint256 public constant VIRTUAL_ASSETS = 1e6;

USDC_INDEX

uint256 private constant USDC_INDEX = 0;

BPS

uint256 private constant BPS = 10_000;

STAKED_INVAR_TIMELOCK

uint256 public constant STAKED_INVAR_TIMELOCK = 7 days;

GAUGE_TIMELOCK

uint256 public constant GAUGE_TIMELOCK = 7 days;

GAUGE_REWARDS_TIMELOCK

uint256 public constant GAUGE_REWARDS_TIMELOCK = 7 days;

State Variables

stakedInvarCoin

sINVAR staking contract that receives harvested yield.

StakedToken public stakedInvarCoin;

pendingStakedInvarCoin

address public pendingStakedInvarCoin;

stakedInvarCoinActivationTime

uint256 public stakedInvarCoinActivationTime;

curveLpCostVp

Cumulative virtual-price cost basis of tracked LP tokens (18 decimals).

Used to isolate fee yield (VP growth) from price appreciation. Only LP tokens deployed by the vault are tracked — donated LP is excluded to prevent yield manipulation.

uint256 public curveLpCostVp;

trackedLpBalance

LP token balance deployed by the vault (excludes donated LP).

uint256 public trackedLpBalance;

emergencyActive

True when emergency mode is active — blocks deposits and single-sided withdrawals.

bool public emergencyActive;

curveGauge

ICurveGauge public curveGauge;

gaugeStakedLp

Internally-tracked LP balance staked in the gauge (avoids external balanceOf dependency).

uint256 public gaugeStakedLp;

pendingGauge

address public pendingGauge;

gaugeActivationTime

uint256 public gaugeActivationTime;

approvedGauges

mapping(address => bool) public approvedGauges;

gaugeRewardsReceiver

address public gaugeRewardsReceiver;

pendingGaugeRewardsReceiver

address public pendingGaugeRewardsReceiver;

gaugeRewardsReceiverActivationTime

uint256 public gaugeRewardsReceiverActivationTime;

protectedRewardTokens

mapping(address => bool) public protectedRewardTokens;

Functions

constructor

constructor(
    address _usdc,
    address _bear,
    address _curveLpToken,
    address _curvePool,
    address _oracle,
    address _sequencerUptimeFeed,
    address _crvMinter
) ERC20("InvarCoin", "INVAR") ERC20Permit("InvarCoin") Ownable(msg.sender);

Parameters

NameTypeDescription
_usdcaddressUSDC token address.
_bearaddressplDXY-BEAR token address.
_curveLpTokenaddressCurve USDC/plDXY-BEAR LP token address.
_curvePooladdressCurve twocrypto-ng pool address.
_oracleaddressBasketOracle address (Chainlink AggregatorV3Interface).
_sequencerUptimeFeedaddressL2 sequencer uptime feed (address(0) on L1).
_crvMinteraddressCurve Minter for CRV emissions (address(0) on L2).

_validateStakingVault

function _validateStakingVault(
    address stakingVault
) private view;

proposeStakedInvarCoin

Propose the sINVAR staking contract. Finalized after STAKED_INVAR_TIMELOCK.

function proposeStakedInvarCoin(
    address _stakedInvarCoin
) external onlyOwner;

Parameters

NameTypeDescription
_stakedInvarCoinaddressAddress of the StakedToken (sINVAR) contract.

finalizeStakedInvarCoin

Finalize the proposed sINVAR staking contract after the timelock.

function finalizeStakedInvarCoin() external onlyOwner;

proposeGaugeRewardsReceiver

Propose the receiver for protected gauge reward tokens.

function proposeGaugeRewardsReceiver(
    address receiver
) external onlyOwner;

finalizeGaugeRewardsReceiver

Finalize the protected reward receiver after the timelock.

function finalizeGaugeRewardsReceiver() external onlyOwner;

_isCoreRewardProtectedAsset

function _isCoreRewardProtectedAsset(
    address token
) private view returns (bool);

protectRewardToken

Irreversibly marks a token as a protected gauge reward token.

function protectRewardToken(
    address token
) external onlyOwner;

sweepGaugeRewards

Sweeps a protected gauge reward token to the configured receiver.

function sweepGaugeRewards(
    address token
) external onlyOwner;

totalAssets

Total assets backing INVAR (USDC, 6 decimals).

Uses pessimistic LP pricing: min(Curve EMA, oracle-derived) to prevent stale-EMA exploitation.

function totalAssets() public view returns (uint256);

totalAssetsValidated

Total assets backing INVAR with strict oracle validation (USDC, 6 decimals).

Reverts if sequencer/oracle checks fail (stale, invalid, or within sequencer grace period).

function totalAssetsValidated() external view returns (uint256);

_totalAssetsWithPrice

Total assets using pre-fetched LP balance and validated oracle price.

function _totalAssetsWithPrice(
    uint256 lpBal,
    uint256 oraclePrice
) private view returns (uint256);

getBufferMetrics

Buffer health metrics for keeper bots and frontends.

Uses permissive totalAssets() (best-effort oracle read). For strict oracle-validated NAV, use totalAssetsValidated().

function getBufferMetrics()
    external
    view
    returns (uint256 currentBuffer, uint256 targetBuffer, uint256 deployable, uint256 replenishable);

Returns

NameTypeDescription
currentBufferuint256USDC held locally (6 decimals).
targetBufferuint256Target USDC buffer based on total assets (6 decimals).
deployableuint256Excess USDC deployable to Curve (0 if below threshold).
replenishableuint256USDC deficit that needs replenishing from Curve LP.

getHarvestableYield

Estimated harvestable Curve fee yield (USDC, 6 decimals).

Read-only estimator mirroring _harvest math. Uses permissive oracle reads and returns 0 if no staking contract, no sINVAR stakers, or no VP growth.

function getHarvestableYield() external view returns (uint256 yieldUsdc);

getSpotDeviation

Spot-vs-EMA deviation for a 1 USDC deposit (basis points).

Returns 0 if spot >= EMA (no discount). Used by keepers to check if deploy/replenish is safe.

function getSpotDeviation() external view returns (uint256 deviationBps);

_totalAssetsOptimistic

Total assets using optimistic LP pricing — max(EMA, oracle) to prevent deposit dilution.

function _totalAssetsOptimistic(
    uint256 oraclePrice
) private view returns (uint256);

_oracleLpPrice

Oracle-derived LP price: mirrors twocrypto-ng formula 2 * vp * sqrt(bearPrice_18dec).

function _oracleLpPrice(
    uint256 oraclePrice
) private view returns (uint256);

_pessimisticLpPrice

function _pessimisticLpPrice(
    uint256 oraclePrice
) private view returns (uint256);

_optimisticLpPrice

function _optimisticLpPrice(
    uint256 oraclePrice
) private view returns (uint256);

_validatedOraclePrice

function _validatedOraclePrice() private view returns (uint256);

_hasStakedInvarSupply

function _hasStakedInvarSupply() private view returns (bool);

_checkpointIfNoStakers

function _checkpointIfNoStakers(
    uint256 currentVpValue
) private returns (bool checkpointed);

_lpBalance

Total LP held: local + gauge-staked (internally tracked to avoid external call dependency).

function _lpBalance() private view returns (uint256);

_ensureUnstakedLp

Unstakes LP from gauge if local balance is insufficient for the requested amount.

function _ensureUnstakedLp(
    uint256 amount
) private;

_outsideSpotDeviationBounds

function _outsideSpotDeviationBounds(
    uint256 spotValue,
    uint256 emaValue
) private pure returns (bool);

_reduceLpAccounting

function _reduceLpAccounting(
    uint256 lpReduced,
    uint256 totalLp
) private;

_recordLpDeployment

function _recordLpDeployment(
    uint256 lpMinted
) private;

_depositToCurve

function _depositToCurve(
    uint256 usdcAmount,
    uint256 bearAmount,
    uint256 oraclePrice
) private returns (uint256 lpMinted);

_stakeLpToGauge

function _stakeLpToGauge(
    uint256 amount
) private;

_validateGaugeAddress

function _validateGaugeAddress(
    address gauge
) private view;

_validateGauge

function _validateGauge(
    address gauge
) private view;

deposit

Deposit USDC to mint INVAR shares. USDC stays in the local buffer until deployed to Curve.

Uses optimistic LP pricing for NAV to prevent deposit dilution. Harvests yield before minting. Reverts while emergencyActive is true.

function deposit(
    uint256 usdcAmount,
    address receiver,
    uint256 minSharesOut
) public nonReentrant whenNotPaused returns (uint256 glUsdMinted);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).
receiveraddressAddress that receives the minted INVAR shares.
minSharesOutuint256Minimum INVAR shares to receive (0 = no minimum).

Returns

NameTypeDescription
glUsdMinteduint256Number of INVAR shares minted.

depositWithPermit

Gasless deposit using ERC-2612 permit. Falls back to existing allowance if permit fails (e.g., front-run griefing) and the allowance is sufficient.

function depositWithPermit(
    uint256 usdcAmount,
    address receiver,
    uint256 minSharesOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external returns (uint256);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals).
receiveraddressAddress that receives the minted INVAR shares.
minSharesOutuint256Minimum INVAR shares to receive (0 = no minimum).
deadlineuint256Permit signature expiry timestamp.
vuint8ECDSA recovery byte.
rbytes32ECDSA r component.
sbytes32ECDSA s component.

Returns

NameTypeDescription
<none>uint256Number of INVAR shares minted.

withdraw

USDC-only withdrawal via pro-rata buffer + JIT Curve LP burn.

Burns the user’s pro-rata share of local USDC and Curve LP (single-sided to USDC). Does not distribute raw BEAR balances — if the contract holds material BEAR, use lpWithdraw() or set minUsdcOut to enforce fair value. Blocked during emergencyActive since single-sided LP exit may be unavailable.

function withdraw(
    uint256 glUsdAmount,
    address receiver,
    uint256 minUsdcOut
) external nonReentrant whenNotPaused returns (uint256 usdcOut);

Parameters

NameTypeDescription
glUsdAmountuint256Amount of INVAR shares to burn.
receiveraddressAddress that receives the withdrawn USDC.
minUsdcOutuint256Minimum USDC to receive (slippage protection).

Returns

NameTypeDescription
usdcOutuint256Total USDC returned (buffer + Curve LP proceeds).

lpWithdraw

Balanced withdrawal: returns pro-rata USDC + BEAR from Curve LP (remove_liquidity).

Intentionally lacks whenNotPaused — serves as the emergency exit when the contract is paused. Emergency mode still honors pro-rata LP claims by redeeming any remaining LP before paying out.

function lpWithdraw(
    uint256 glUsdAmount,
    uint256 minUsdcOut,
    uint256 minBearOut,
    address receiver
) external nonReentrant returns (uint256 usdcReturned, uint256 bearReturned);

Parameters

NameTypeDescription
glUsdAmountuint256Amount of INVAR shares to burn.
minUsdcOutuint256Minimum USDC to receive (slippage protection).
minBearOutuint256Minimum plDXY-BEAR to receive (slippage protection).
receiveraddressAddress receiving the withdrawn assets.

Returns

NameTypeDescription
usdcReturneduint256Total USDC returned.
bearReturneduint256Total plDXY-BEAR returned.

_lpWithdraw

function _lpWithdraw(
    uint256 glUsdAmount,
    uint256 minUsdcOut,
    uint256 minBearOut,
    address receiver
) internal returns (uint256 usdcReturned, uint256 bearReturned);

lpDeposit

Direct LP deposit: provide USDC and/or plDXY-BEAR, deploy to Curve, mint INVAR.

Inverse of lpWithdraw. Curve slippage is borne by the depositor, not existing holders. Shares are priced using pessimistic LP valuation so the depositor cannot extract value from a stale-high EMA. Spot deviation is checked against EMA to block sandwich attacks. Reverts while emergencyActive is true.

function lpDeposit(
    uint256 usdcAmount,
    uint256 bearAmount,
    address receiver,
    uint256 minSharesOut
) external nonReentrant whenNotPaused returns (uint256 glUsdMinted);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to deposit (6 decimals, can be 0 if bearAmount > 0).
bearAmountuint256Amount of plDXY-BEAR to deposit (18 decimals, can be 0 if usdcAmount > 0).
receiveraddressAddress that receives the minted INVAR shares.
minSharesOutuint256Minimum INVAR shares to receive (slippage protection).

Returns

NameTypeDescription
glUsdMinteduint256Number of INVAR shares minted.

harvest

Permissionless keeper harvest for Curve LP fee yield.

Measures fee yield as virtual price growth above the cost basis (curveLpCostVp). Mints INVAR proportional to the USDC value of yield and donates it to sINVAR stakers. Only tracks VP growth on vault-deployed LP (trackedLpBalance), not donated LP. Reverts if no yield is available to donate or checkpoint — use as a heartbeat signal for keepers.

function harvest() external nonReentrant whenNotPaused returns (uint256 donated);

Returns

NameTypeDescription
donateduint256Amount of INVAR minted and donated to sINVAR.

_harvestSafe

Harvest yield before withdrawals. Best-effort: skips when no yield is pending, Curve is down, or oracle is unavailable. If no sINVAR recipients exist, checkpoints VP growth as INVAR NAV. Withdrawals must never be blocked.

function _harvestSafe() internal;

_harvest

Uses trackedLpBalance (not _lpBalance()) so donated LP cannot inflate harvestable yield. Divergence from actual LP is prevented by internal gaugeStakedLp tracking and forceRemoveGauge() which writes off stuck LP from both trackedLpBalance and curveLpCostVp.

function _harvest() internal returns (uint256 donated, bool accounted);

_mintAndDonate

function _mintAndDonate(
    uint256 amount
) private;

_harvestWithPrice

function _harvestWithPrice(
    uint256 lpBal,
    uint256 currentVpValue,
    uint256 oraclePrice
) private returns (uint256 donated, bool accounted);

donateUsdc

Accepts USDC donations from RewardDistributor, mints proportional INVAR, and donates to sINVAR.

function donateUsdc(
    uint256 usdcAmount
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to donate (6 decimals).

previewSellLpToVault

Preview USDC paid when a solver sells Curve LP to the vault.

Uses the pessimistic fair LP price less SOLVER_PRICE_SPREAD_BPS as the vault bid.

function previewSellLpToVault(
    uint256 lpAmount
) external view returns (uint256 usdcOut);

previewBuyLpFromVault

Preview USDC required when a solver buys Curve LP from the vault.

Uses the optimistic fair LP price plus SOLVER_PRICE_SPREAD_BPS as the vault ask.

function previewBuyLpFromVault(
    uint256 lpAmount
) external view returns (uint256 usdcIn);

sellLpToVault

Permissionless solver fill: solver sells Curve LP to the vault for excess USDC buffer.

The vault never trades on Curve; the solver owns sourcing/slippage risk.

function sellLpToVault(
    uint256 lpAmount,
    uint256 minUsdcOut
) external nonReentrant whenNotPaused returns (uint256 usdcOut);

Parameters

NameTypeDescription
lpAmountuint256Amount of Curve LP transferred from the solver.
minUsdcOutuint256Minimum USDC the solver is willing to receive.

Returns

NameTypeDescription
usdcOutuint256USDC paid to the solver.

buyLpFromVault

Permissionless solver fill: solver buys Curve LP from the vault and restores USDC buffer.

The vault never trades on Curve; the solver owns exit/slippage risk.

function buyLpFromVault(
    uint256 lpAmount,
    uint256 maxUsdcIn
) external nonReentrant whenNotPaused returns (uint256 usdcIn);

Parameters

NameTypeDescription
lpAmountuint256Amount of Curve LP bought from the vault.
maxUsdcInuint256Maximum USDC the solver is willing to pay.

Returns

NameTypeDescription
usdcInuint256USDC paid by the solver.

redeployToCurve

Re-deploys recovered BEAR + excess USDC to Curve after emergency recovery.

Clears emergencyActive flag. Should only be called after emergencyWithdrawFromCurve() has recovered the BEAR tokens from the pool.

function redeployToCurve(
    uint256 minLpOut
) external onlyOwner nonReentrant;

Parameters

NameTypeDescription
minLpOutuint256Minimum LP tokens to mint (slippage protection for the two-sided deposit).

setEmergencyMode

Activates emergency mode without touching Curve.

Pauses the contract and blocks deposits plus single-sided withdrawals. LP accounting is left intact so users retain their pro-rata claim once balanced exits recover.

function setEmergencyMode() external onlyOwner;

forceRemoveGauge

Write off a bricked gauge and its stuck LP from accounting.

Only callable during emergencyActive. Clears curveGauge, proportionally reduces trackedLpBalance and curveLpCostVp for the lost LP, and zeros gaugeStakedLp. After this, emergencyWithdrawFromCurve() or lpWithdraw() can proceed with remaining local LP.

function forceRemoveGauge() external onlyOwner;

emergencyWithdrawFromCurve

Attempts to recover LP tokens from Curve via balanced remove_liquidity.

Also callable as a standalone emergency — sets emergencyActive, pauses, and only zeroes tracked LP accounting after the LP has actually been recovered. If Curve is bricked, the remove_liquidity call reverts and the entire tx rolls back, leaving state unchanged. Use setEmergencyMode() first in that case.

function emergencyWithdrawFromCurve() external onlyOwner nonReentrant;

setGaugeApproval

function setGaugeApproval(
    address gauge,
    bool approved
) external onlyOwner;

pause

function pause() external onlyOwner;

unpause

function unpause() external onlyOwner;

rescueToken

Rescue accidentally sent ERC20 tokens. Cannot rescue USDC, BEAR, or Curve LP.

function rescueToken(
    address token,
    address to
) external onlyOwner;

Parameters

NameTypeDescription
tokenaddressAddress of the token to rescue.
toaddressDestination address for the rescued tokens.

proposeGauge

Propose a new Curve gauge for LP staking. Subject to GAUGE_TIMELOCK delay.

function proposeGauge(
    address _gauge
) external onlyOwner;

Parameters

NameTypeDescription
_gaugeaddressAddress of the new gauge (address(0) to remove gauge).

finalizeGauge

Finalize a pending gauge change after the timelock expires.

This MUST revert if oldGauge.withdraw() fails. Do NOT wrap in try/catch: silent failure would update curveGauge to newGauge while LP stays locked in oldGauge, causing _lpBalance() to forget the stuck LP and collapsing totalAssets(). If the old gauge is permanently bricked, use setEmergencyMode() instead.

function finalizeGauge() external onlyOwner;

stakeToGauge

Stake LP tokens to the active Curve gauge.

function stakeToGauge(
    uint256 amount
) external onlyOwner;

Parameters

NameTypeDescription
amountuint256Amount of LP to stake (0 = all unstaked LP).

unstakeFromGauge

Unstake LP tokens from the active Curve gauge.

function unstakeFromGauge(
    uint256 amount
) external onlyOwner;

Parameters

NameTypeDescription
amountuint256Amount of LP to unstake (0 = all staked LP).

claimGaugeRewards

Claim CRV + extra rewards from the gauge. Use rescueToken() to sweep reward tokens.

On L1, CRV is minted via the Curve Minter (not claim_rewards). On L2, claim_rewards handles CRV.

function claimGaugeRewards() external onlyOwner;

Events

Deposited

event Deposited(address indexed user, address indexed receiver, uint256 usdcIn, uint256 glUsdOut);

Withdrawn

event Withdrawn(address indexed user, address indexed receiver, uint256 glUsdIn, uint256 usdcOut);

LpWithdrawn

event LpWithdrawn(
    address indexed user, address indexed receiver, uint256 sharesBurned, uint256 usdcReturned, uint256 bearReturned
);

LpDeposited

event LpDeposited(address indexed user, address indexed receiver, uint256 usdcIn, uint256 bearIn, uint256 glUsdOut);

DeployedToCurve

event DeployedToCurve(address indexed caller, uint256 usdcDeployed, uint256 bearDeployed, uint256 lpMinted);

SolverLpPurchased

event SolverLpPurchased(address indexed solver, uint256 lpIn, uint256 usdcOut);

SolverLpSold

event SolverLpSold(address indexed solver, uint256 lpOut, uint256 usdcIn);

YieldHarvested

event YieldHarvested(uint256 glUsdMinted, uint256 callerReward, uint256 donated);

TokenRescued

event TokenRescued(address indexed token, address indexed to, uint256 amount);

EmergencyWithdrawCurve

event EmergencyWithdrawCurve(uint256 lpBurned, uint256 usdcReceived, uint256 bearReceived);

StakedInvarCoinProposed

event StakedInvarCoinProposed(address indexed stakedInvarCoin, uint256 activationTime);

StakedInvarCoinSet

event StakedInvarCoinSet(address indexed stakedInvarCoin);

GaugeProposed

event GaugeProposed(address indexed gauge, uint256 activationTime);

GaugeUpdated

event GaugeUpdated(address indexed oldGauge, address indexed newGauge);

GaugeRewardsReceiverProposed

event GaugeRewardsReceiverProposed(address indexed receiver, uint256 activationTime);

GaugeRewardsReceiverSet

event GaugeRewardsReceiverSet(address indexed receiver);

RewardTokenProtected

event RewardTokenProtected(address indexed token);

GaugeStaked

event GaugeStaked(uint256 amount);

GaugeUnstaked

event GaugeUnstaked(uint256 amount);

GaugeRewardsClaimed

event GaugeRewardsClaimed();

GaugeRewardsSwept

event GaugeRewardsSwept(address indexed token, address indexed receiver, uint256 amount);

UsdcDonated

event UsdcDonated(address indexed donor, uint256 usdcAmount, uint256 invarMinted);

GaugeForceRemoved

event GaugeForceRemoved(address indexed gauge, uint256 lpLost);

Errors

InvarCoin__ZeroAmount

error InvarCoin__ZeroAmount();

InvarCoin__StakingNotSet

error InvarCoin__StakingNotSet();

InvarCoin__ZeroAddress

error InvarCoin__ZeroAddress();

InvarCoin__SlippageExceeded

error InvarCoin__SlippageExceeded();

InvarCoin__NothingToDeploy

error InvarCoin__NothingToDeploy();

InvarCoin__NoYield

error InvarCoin__NoYield();

InvarCoin__CannotRescueCoreAsset

error InvarCoin__CannotRescueCoreAsset();

InvarCoin__PermitFailed

error InvarCoin__PermitFailed();

InvarCoin__AlreadySet

error InvarCoin__AlreadySet();

InvarCoin__SpotDeviationTooHigh

error InvarCoin__SpotDeviationTooHigh();

InvarCoin__UseLpWithdraw

error InvarCoin__UseLpWithdraw();

InvarCoin__Unauthorized

error InvarCoin__Unauthorized();

InvarCoin__NoStakers

error InvarCoin__NoStakers();

InvarCoin__GaugeTimelockActive

error InvarCoin__GaugeTimelockActive();

InvarCoin__StakingTimelockActive

error InvarCoin__StakingTimelockActive();

InvarCoin__GaugeRewardsTimelockActive

error InvarCoin__GaugeRewardsTimelockActive();

InvarCoin__InvalidProposal

error InvarCoin__InvalidProposal();

InvarCoin__NoGauge

error InvarCoin__NoGauge();

InvarCoin__EmergencyActive

error InvarCoin__EmergencyActive();

InvarCoin__InvalidGauge

error InvarCoin__InvalidGauge();

InvarCoin__InvalidStakingVault

error InvarCoin__InvalidStakingVault();

InvarCoin__GaugeRewardsReceiverNotSet

error InvarCoin__GaugeRewardsReceiverNotSet();

InvarCoin__NotEmergency

error InvarCoin__NotEmergency();

LeverageRouter

Git Source

Inherits: LeverageRouterBase

Title: LeverageRouter

Leverage router for plDXY-BEAR positions via Morpho Blue.

Flash loans USDC from Morpho → swaps to plDXY-BEAR on Curve → stakes → deposits to Morpho as collateral. Requires user to authorize this contract in Morpho before use. Uses Morpho’s fee-free flash loans for capital efficiency.

Note: security-contact: contact@plether.com

Constants

STAKED_PLDXY_BEAR

StakedToken vault for plDXY-BEAR (used as Morpho collateral).

IERC4626 public immutable STAKED_PLDXY_BEAR;

Functions

constructor

Deploys LeverageRouter with Morpho market configuration.

constructor(
    address _morpho,
    address _curvePool,
    address _usdc,
    address _plDxyBear,
    address _stakedPlDxyBear,
    MarketParams memory _marketParams
) LeverageRouterBase(_morpho, _curvePool, _usdc, _plDxyBear);

Parameters

NameTypeDescription
_morphoaddressMorpho Blue protocol address.
_curvePooladdressCurve USDC/plDXY-BEAR pool address.
_usdcaddressUSDC token address.
_plDxyBearaddressplDXY-BEAR token address.
_stakedPlDxyBearaddresssplDXY-BEAR staking vault address.
_marketParamsMarketParamsMorpho market parameters for splDXY-BEAR/USDC.

openLeverage

Open a Leveraged Position in one transaction.

function openLeverage(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
principaluint256Amount of USDC user sends.
leverageuint256Multiplier (e.g. 3x = 3e18).
maxSlippageBpsuint256Maximum slippage tolerance in basis points (e.g., 50 = 0.5%). Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

openLeverageWithPermit

Open a leveraged position with a USDC permit signature (gasless approval).

function openLeverageWithPermit(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
principaluint256Amount of USDC user sends.
leverageuint256Multiplier (e.g. 3x = 3e18).
maxSlippageBpsuint256Maximum slippage tolerance in basis points.
minAmountOutuint256
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_openLeverageCore

function _openLeverageCore(
    uint256 principal,
    uint256 leverage,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) internal;

closeLeverage

Close a Leveraged Position in one transaction.

Queries actual debt from Morpho to ensure full repayment even if interest accrued.

function closeLeverage(
    uint256 collateralToWithdraw,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BEAR shares to withdraw from Morpho. NOTE: This is staked token shares, not underlying plDXY-BEAR amount. Use STAKED_PLDXY_BEAR.previewRedeem() to convert shares to underlying.
maxSlippageBpsuint256Maximum slippage tolerance in basis points (e.g., 50 = 0.5%). Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

addCollateral

Add collateral to an existing leveraged position.

Swaps USDC to plDXY-BEAR on Curve, stakes, and deposits to Morpho.

function addCollateral(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to add as collateral.
maxSlippageBpsuint256Maximum slippage tolerance in basis points. Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

addCollateralWithPermit

Add collateral with a USDC permit signature (gasless approval).

function addCollateralWithPermit(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to add as collateral.
maxSlippageBpsuint256Maximum slippage tolerance in basis points.
minAmountOutuint256
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_addCollateralCore

function _addCollateralCore(
    uint256 usdcAmount,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) internal;

removeCollateral

Remove collateral from an existing leveraged position.

Withdraws from Morpho, unstakes, and swaps to USDC. Reverts if the resulting position would be unhealthy.

function removeCollateral(
    uint256 collateralToWithdraw,
    uint256 maxSlippageBps,
    uint256 minAmountOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BEAR shares to withdraw. NOTE: This is staked token shares, not underlying plDXY-BEAR amount.
maxSlippageBpsuint256Maximum slippage tolerance in basis points. Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
minAmountOutuint256
deadlineuint256Unix timestamp after which the transaction reverts.

onMorphoFlashLoan

Morpho flash loan callback. Routes to open or close handler.

function onMorphoFlashLoan(
    uint256 amount,
    bytes calldata data
) external override;

Parameters

NameTypeDescription
amountuint256Amount of USDC borrowed.
databytesEncoded operation parameters.

onFlashLoan

ERC-3156 flash loan callback - not used by LeverageRouter.

Always reverts as LeverageRouter only uses Morpho flash loans.

function onFlashLoan(
    address,
    address,
    uint256,
    uint256,
    bytes calldata
) external pure override returns (bytes32);

_executeOpen

Executes open leverage operation within Morpho flash loan callback.

function _executeOpen(
    uint256 loanAmount,
    bytes calldata data
) private;

Parameters

NameTypeDescription
loanAmountuint256Amount of USDC borrowed from Morpho.
databytesEncoded parameters (op, user, deadline, principal, leverage, maxSlippageBps, minPlDxyBear, minAmountOut).

_executeClose

Executes close leverage operation within Morpho flash loan callback.

function _executeClose(
    uint256 loanAmount,
    bytes calldata data
) private;

Parameters

NameTypeDescription
loanAmountuint256Amount of USDC borrowed from Morpho to repay debt.
databytesEncoded parameters (op, user, deadline, collateralToWithdraw, borrowShares, maxSlippageBps, minUsdcOut, minAmountOut).

_executeCloseNoDebt

Closes position without flash loan when user has no Morpho debt.

function _executeCloseNoDebt(
    address user,
    uint256 collateralToWithdraw,
    uint256 maxSlippageBps,
    uint256 minUsdcOut,
    uint256 minAmountOut
) private;

Parameters

NameTypeDescription
useraddressPosition owner receiving USDC.
collateralToWithdrawuint256Amount of splDXY-BEAR shares to withdraw.
maxSlippageBpsuint256Maximum slippage for Curve swap.
minUsdcOutuint256Minimum USDC to receive after swap.
minAmountOutuint256User-provided minimum USDC to receive (MEV protection).

previewOpenLeverage

Preview the result of opening a leveraged position.

function previewOpenLeverage(
    uint256 principal,
    uint256 leverage
) external view returns (uint256 loanAmount, uint256 totalUSDC, uint256 expectedPlDxyBear, uint256 expectedDebt);

Parameters

NameTypeDescription
principaluint256Amount of USDC user will send.
leverageuint256Multiplier (e.g. 3x = 3e18).

Returns

NameTypeDescription
loanAmountuint256Amount of USDC to flash loan.
totalUSDCuint256Total USDC to swap (principal + loan).
expectedPlDxyBearuint256Expected plDXY-BEAR (based on current curve price).
expectedDebtuint256Expected debt incurred (equals loan amount, no flash fee with Morpho).

previewCloseLeverage

Preview the result of closing a leveraged position.

function previewCloseLeverage(
    uint256 debtToRepay,
    uint256 collateralToWithdraw
) external view returns (uint256 expectedUSDC, uint256 flashFee, uint256 expectedReturn);

Parameters

NameTypeDescription
debtToRepayuint256Amount of USDC debt to repay.
collateralToWithdrawuint256Amount of plDXY-BEAR collateral to withdraw.

Returns

NameTypeDescription
expectedUSDCuint256Expected USDC from swap (based on current curve price).
flashFeeuint256Flash loan fee (always 0 with Morpho).
expectedReturnuint256Expected USDC returned to user after repaying flash loan.

previewAddCollateral

Preview the result of adding collateral.

function previewAddCollateral(
    uint256 usdcAmount
) external view returns (uint256 expectedPlDxyBear, uint256 expectedStakedShares);

Parameters

NameTypeDescription
usdcAmountuint256Amount of USDC to add as collateral.

Returns

NameTypeDescription
expectedPlDxyBearuint256Expected plDXY-BEAR from Curve swap.
expectedStakedSharesuint256Expected splDXY-BEAR shares to receive.

previewRemoveCollateral

Preview the result of removing collateral.

function previewRemoveCollateral(
    uint256 collateralToWithdraw
) external view returns (uint256 expectedPlDxyBear, uint256 expectedUSDC);

Parameters

NameTypeDescription
collateralToWithdrawuint256Amount of splDXY-BEAR shares to withdraw.

Returns

NameTypeDescription
expectedPlDxyBearuint256Expected plDXY-BEAR from unstaking.
expectedUSDCuint256Expected USDC from Curve swap.

Events

LeverageOpened

Emitted when a leveraged plDXY-BEAR position is opened.

event LeverageOpened(
    address indexed user,
    uint256 principal,
    uint256 leverage,
    uint256 loanAmount,
    uint256 plDxyBearReceived,
    uint256 debtIncurred,
    uint256 maxSlippageBps
);

LeverageClosed

Emitted when a leveraged plDXY-BEAR position is closed.

event LeverageClosed(
    address indexed user,
    uint256 debtRepaid,
    uint256 collateralWithdrawn,
    uint256 usdcReturned,
    uint256 maxSlippageBps
);

CollateralAdded

Emitted when collateral is added to a position.

usdcReturned is always 0 for BEAR router (full amount swapped to BEAR).

event CollateralAdded(
    address indexed user, uint256 usdcAmount, uint256 usdcReturned, uint256 collateralAdded, uint256 maxSlippageBps
);

CollateralRemoved

Emitted when collateral is removed from a position.

event CollateralRemoved(
    address indexed user, uint256 collateralWithdrawn, uint256 usdcReturned, uint256 maxSlippageBps
);

RewardDistributor

Git Source

Inherits: IRewardDistributor, ReentrancyGuard

Title: RewardDistributor

Distributes staking rewards based on price discrepancy between oracle and Curve EMA.

Receives USDC from SyntheticSplitter.harvestYield() and allocates to StakedToken vaults proportionally based on which token is underperforming relative to theoretical price.

Note: security-contact: contact@plether.com

Constants

DISCREPANCY_THRESHOLD_BPS

Discrepancy threshold for 100% allocation (2% = 200 bps).

uint256 public constant DISCREPANCY_THRESHOLD_BPS = 200;

MIN_DISTRIBUTION_INTERVAL

Minimum time between distributions (1 hour).

uint256 public constant MIN_DISTRIBUTION_INTERVAL = 1 hours;

CALLER_REWARD_BPS

Reward for calling distributeRewards (0.1% = 10 bps).

uint256 public constant CALLER_REWARD_BPS = 10;

USDC_INDEX

USDC index in Curve pool.

uint256 public constant USDC_INDEX = 0;

PLDXY_BEAR_INDEX

plDXY-BEAR index in Curve pool.

uint256 public constant PLDXY_BEAR_INDEX = 1;

MAX_SWAP_SLIPPAGE_BPS

Maximum slippage for Curve swaps (1% = 100 bps).

uint256 public constant MAX_SWAP_SLIPPAGE_BPS = 100;

MAX_ORACLE_ZAP_SLIPPAGE_BPS

Maximum slippage for oracle-based zap estimates (3% = 300 bps).

Wider than MAX_SWAP_SLIPPAGE_BPS because ZapRouter’s flash mint loop adds fees.

uint256 public constant MAX_ORACLE_ZAP_SLIPPAGE_BPS = 300;

ORACLE_TIMEOUT

Maximum age for oracle price data (24 hours to match Chainlink CHF/CAD heartbeat).

uint256 public constant ORACLE_TIMEOUT = 24 hours;

SPLITTER

SyntheticSplitter contract.

ISyntheticSplitter public immutable SPLITTER;

USDC

USDC stablecoin.

IERC20 public immutable USDC;

PLDXY_BEAR

plDXY-BEAR token.

IERC20 public immutable PLDXY_BEAR;

PLDXY_BULL

plDXY-BULL token.

IERC20 public immutable PLDXY_BULL;

STAKED_BEAR

Staked plDXY-BEAR vault.

StakedToken public immutable STAKED_BEAR;

STAKED_BULL

Staked plDXY-BULL vault.

StakedToken public immutable STAKED_BULL;

CURVE_POOL

Curve USDC/plDXY-BEAR pool.

ICurvePool public immutable CURVE_POOL;

ZAP_ROUTER

ZapRouter for acquiring plDXY-BULL.

ZapRouter public immutable ZAP_ROUTER;

ORACLE

BasketOracle for theoretical price.

AggregatorV3Interface public immutable ORACLE;

PYTH_ADAPTER

Optional PythAdapter for SEK/USD price updates (address(0) if not used).

PythAdapter public immutable PYTH_ADAPTER;

INVAR_COIN

Optional InvarCoin vault that receives a share of BEAR rewards (address(0) if not used).

IInvarCoin public immutable INVAR_COIN;

CAP

Protocol CAP price (8 decimals).

uint256 public immutable CAP;

State Variables

lastDistributionTime

Timestamp of last distribution.

uint256 public lastDistributionTime;

Functions

constructor

Deploys RewardDistributor with all required dependencies.

constructor(
    address _splitter,
    address _usdc,
    address _plDxyBear,
    address _plDxyBull,
    address _stakedBear,
    address _stakedBull,
    address _curvePool,
    address _zapRouter,
    address _oracle,
    address _pythAdapter,
    address _invarCoin
);

Parameters

NameTypeDescription
_splitteraddressSyntheticSplitter contract address.
_usdcaddressUSDC token address.
_plDxyBearaddressplDXY-BEAR token address.
_plDxyBulladdressplDXY-BULL token address.
_stakedBearaddressStakedToken vault for BEAR.
_stakedBulladdressStakedToken vault for BULL.
_curvePooladdressCurve USDC/plDXY-BEAR pool.
_zapRouteraddressZapRouter for BULL acquisition.
_oracleaddressBasketOracle for price data.
_pythAdapteraddressOptional PythAdapter for SEK/USD updates (address(0) if not used).
_invarCoinaddressOptional InvarCoin vault for BEAR reward split (address(0) if not used).

receive

receive() external payable;

distributeRewards

Permissionless function to distribute accumulated USDC rewards.

Calculates price discrepancy, acquires tokens, and donates to vaults.

function distributeRewards() external nonReentrant returns (uint256 callerReward);

Returns

NameTypeDescription
callerRewarduint256Amount of USDC sent to caller as incentive.

_distributeRewardsInternal

Internal implementation of reward distribution.

function _distributeRewardsInternal() internal returns (uint256 callerReward);

_allocateRewards

function _allocateRewards(
    uint256 distributableUsdc,
    uint256 bearPct,
    uint256 bullPct
) internal pure returns (uint256 bearUsdc, uint256 bullUsdc);

_prepareBearAllocation

function _prepareBearAllocation(
    uint256 bearUsdc,
    uint256 absBasketPrice
) internal returns (uint256 stakedBearUsdc, uint256 invarUsdcAmount);

_distributeAcquiredTokens

function _distributeAcquiredTokens(
    uint256 bearAmount,
    uint256 bullAmount
) internal;

distributeRewardsWithPriceUpdate

Distributes rewards after updating the Pyth oracle price.

Bundles Pyth price update with reward distribution to save gas. Caller receives the same reward as distributeRewards().

function distributeRewardsWithPriceUpdate(
    bytes[] calldata pythUpdateData
) external payable nonReentrant returns (uint256 callerReward);

Parameters

NameTypeDescription
pythUpdateDatabytes[]Price update data from Pyth Hermes API.

Returns

NameTypeDescription
callerRewarduint256Amount of USDC sent to caller as incentive.

previewDistribution

Preview the distribution without executing.

function previewDistribution()
    external
    view
    returns (uint256 bearPct, uint256 bullPct, uint256 usdcBalance, uint256 callerReward);

Returns

NameTypeDescription
bearPctuint256Expected percentage to BEAR stakers (basis points).
bullPctuint256Expected percentage to BULL stakers (basis points).
usdcBalanceuint256Current USDC balance available for distribution.
callerRewarduint256Expected caller reward.

_calculateSplit

Calculates reward split based on price discrepancy.

function _calculateSplit(
    uint256 absBasketPrice
) internal view returns (uint256 bearPct, uint256 bullPct);

Parameters

NameTypeDescription
absBasketPriceuint256Validated basket price (8 decimals, positive).

Returns

NameTypeDescription
bearPctuint256Percentage for BEAR stakers (basis points).
bullPctuint256Percentage for BULL stakers (basis points).

_acquireTokens

Acquires tokens using optimal combination of minting and swapping/zapping.

function _acquireTokens(
    uint256 bearUsdc,
    uint256 bullUsdc,
    uint256 absBasketPrice
) internal returns (uint256 bearAmount, uint256 bullAmount);

Parameters

NameTypeDescription
bearUsdcuint256USDC allocated to BEAR acquisition.
bullUsdcuint256USDC allocated to BULL acquisition.
absBasketPriceuint256Validated basket price (8 decimals, positive).

Returns

NameTypeDescription
bearAmountuint256Amount of plDXY-BEAR acquired.
bullAmountuint256Amount of plDXY-BULL acquired.

rescueUsdc

Rescues USDC trapped after protocol liquidation.

Only callable when Splitter is SETTLED. Sends full USDC balance to Splitter treasury.

function rescueUsdc() external;

_splitBearAllocation

Splits BEAR-side USDC allocation between StakedBear and InvarCoin proportional to BEAR exposure.

function _splitBearAllocation(
    uint256 bearUsdc,
    uint256 absBasketPrice
) internal view returns (uint256 stakedUsdc, uint256 invarUsdc);

Parameters

NameTypeDescription
bearUsdcuint256Total USDC allocated to the BEAR side.
absBasketPriceuint256Validated basket price (8 decimals, positive).

_calculateMintAmount

Converts USDC amount to 18-decimal mint amount.

function _calculateMintAmount(
    uint256 usdcAmount
) internal view returns (uint256 mintAmount);

Parameters

NameTypeDescription
usdcAmountuint256USDC amount (6 decimals).

Returns

NameTypeDescription
mintAmountuint256Token amount to mint (18 decimals).

StakedToken

Git Source

Inherits: ERC4626

Title: StakedToken

ERC4626 vault for staking plDXY-BEAR or plDXY-BULL tokens.

Used as Morpho collateral. Exchange rate increases via yield donations. Implements 1000x virtual share offset to prevent inflation attacks. Implements streaming rewards (1-hour linear vest) to prevent reward sniping.

Note: security-contact: contact@plether.com

Constants

STREAM_DURATION

Duration over which donated rewards are streamed.

uint256 public constant STREAM_DURATION = 1 hours;

State Variables

_trackedBalance

uint256 private _trackedBalance;

rewardRate

Current reward streaming rate (tokens per second, scaled by 1e18).

uint256 public rewardRate;

streamEndTime

Timestamp when current reward stream ends.

uint256 public streamEndTime;

Functions

constructor

Creates a new staking vault for a synthetic token.

constructor(
    IERC20 _asset,
    string memory _name,
    string memory _symbol
) ERC4626(_asset) ERC20(_name, _symbol);

Parameters

NameTypeDescription
_assetIERC20The underlying plDXY token to stake (plDXY-BEAR or plDXY-BULL).
_namestringVault share name (e.g., “Staked plDXY-BEAR”).
_symbolstringVault share symbol (e.g., “splDXY-BEAR”).

totalAssets

Returns total assets including only vested streamed rewards.

Overrides ERC4626 to exclude unvested rewards from share price calculation.

function totalAssets() public view override returns (uint256);

donateYield

Donates yield that streams to stakers over STREAM_DURATION.

Rewards vest linearly. New donations extend the stream proportionally to the donation size, preventing griefing via zero-amount timer resets.

function donateYield(
    uint256 amount
) external;

Parameters

NameTypeDescription
amountuint256The amount of underlying tokens to donate.

depositWithPermit

Deposit assets with a permit signature (gasless approval).

Combines EIP-2612 permit with ERC-4626 deposit in a single transaction.

function depositWithPermit(
    uint256 assets,
    address receiver,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of underlying tokens to deposit
receiveraddressAddress to receive the vault shares
deadlineuint256Permit signature expiration timestamp
vuint8Signature recovery byte
rbytes32Signature r component
sbytes32Signature s component

Returns

NameTypeDescription
sharesuint256Amount of vault shares minted

_deposit

function _deposit(
    address caller,
    address receiver,
    uint256 assets,
    uint256 shares
) internal override;

_withdraw

function _withdraw(
    address caller,
    address receiver,
    address owner,
    uint256 assets,
    uint256 shares
) internal override;

_unvestedRewards

Calculates unvested rewards from the current stream.

function _unvestedRewards() internal view returns (uint256);

_decimalsOffset

Virtual share offset (10^3 = 1000x) to prevent inflation attacks.

function _decimalsOffset() internal pure override returns (uint8);

Events

YieldDonated

Emitted when yield is donated and streaming begins/extends.

event YieldDonated(address indexed donor, uint256 amount, uint256 newStreamEndTime);

Errors

StakedToken__NoStakers

error StakedToken__NoStakers();

StakedToken__PermitFailed

error StakedToken__PermitFailed();

SyntheticSplitter

Git Source

Inherits: ISyntheticSplitter, Ownable2Step, Pausable, ReentrancyGuard

Title: SyntheticSplitter

Core protocol contract for minting/burning synthetic plDXY tokens.

Accepts USDC collateral to mint equal amounts of plDXY-BEAR + plDXY-BULL tokens. Minted USDC stays local; a permissionless deployToAdapter() pushes excess above the 10% buffer into the yield adapter. Three lifecycle states: ACTIVE → PAUSED → SETTLED.

Note: security-contact: contact@plether.com

Constants

BEAR

SyntheticToken public immutable BEAR;

BULL

SyntheticToken public immutable BULL;

USDC

IERC20 public immutable USDC;

ORACLE

AggregatorV3Interface public immutable ORACLE;

CAP

uint256 public immutable CAP;

USDC_DECIMALS

uint256 private constant USDC_DECIMALS = 6;

USDC_MULTIPLIER

uint256 public constant USDC_MULTIPLIER = 10 ** (18 + 8 - USDC_DECIMALS);

BUFFER_PERCENT

uint256 public constant BUFFER_PERCENT = 10;

ORACLE_TIMEOUT

uint256 public constant ORACLE_TIMEOUT = 24 hours;

TIMELOCK_DELAY

uint256 public constant TIMELOCK_DELAY = 7 days;

HARVEST_REWARD_BPS

uint256 public constant HARVEST_REWARD_BPS = 10;

MIN_SURPLUS_THRESHOLD

uint256 public constant MIN_SURPLUS_THRESHOLD = 50 * 10 ** USDC_DECIMALS;

MIN_DEPLOY_AMOUNT

uint256 public constant MIN_DEPLOY_AMOUNT = 100 * 10 ** USDC_DECIMALS;

SEQUENCER_UPTIME_FEED

AggregatorV3Interface public immutable SEQUENCER_UPTIME_FEED;

SEQUENCER_GRACE_PERIOD

uint256 public constant SEQUENCER_GRACE_PERIOD = 1 hours;

State Variables

yieldAdapter

IERC4626 public yieldAdapter;

pendingAdapter

address public pendingAdapter;

adapterActivationTime

uint256 public adapterActivationTime;

treasury

address public treasury;

staking

address public staking;

pendingFees

FeeConfig public pendingFees;

feesActivationTime

uint256 public feesActivationTime;

lastUnpauseTime

uint256 public lastUnpauseTime;

isLiquidated

bool public isLiquidated;

liquidationTimestamp

uint256 public liquidationTimestamp;

Functions

constructor

Deploys the SyntheticSplitter and creates plDXY-BEAR and plDXY-BULL tokens.

constructor(
    address _oracle,
    address _usdc,
    address _yieldAdapter,
    uint256 _cap,
    address _treasury,
    address _sequencerUptimeFeed
) Ownable(msg.sender);

Parameters

NameTypeDescription
_oracleaddressChainlink-compatible price feed for plDXY basket.
_usdcaddressUSDC token address (6 decimals).
_yieldAdapteraddressERC4626-compliant yield adapter for USDC deposits.
_capuint256Maximum plDXY price (8 decimals). Triggers liquidation when breached.
_treasuryaddressTreasury address for fee distribution.
_sequencerUptimeFeedaddressL2 sequencer uptime feed (address(0) for L1/testnets).

previewMint

Simulates a mint to see required USDC input

function previewMint(
    uint256 mintAmount
) external view returns (uint256 usdcRequired, uint256 depositToAdapter, uint256 keptInBuffer);

Parameters

NameTypeDescription
mintAmountuint256The amount of TokenA/B the user wants to mint

Returns

NameTypeDescription
usdcRequireduint256Total USDC needed from user
depositToAdapteruint256Always 0 (deployment is separate via deployToAdapter())
keptInBufferuint256Amount that will stay in Splitter contract (equals usdcRequired)

mint

Mint plDXY-BEAR and plDXY-BULL tokens by depositing USDC collateral.

function mint(
    uint256 amount
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to mint (18 decimals).

mintWithPermit

Mint plDXY-BEAR and plDXY-BULL tokens with a USDC permit signature (gasless approval).

function mintWithPermit(
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to mint (18 decimals).
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_mintCore

function _mintCore(
    uint256 amount
) internal;

previewBurn

Simulates a burn to see USDC return

function previewBurn(
    uint256 burnAmount
) external view returns (uint256 usdcRefund, uint256 withdrawnFromAdapter);

Parameters

NameTypeDescription
burnAmountuint256The amount of TokenA/B the user wants to burn

Returns

NameTypeDescription
usdcRefunduint256Total USDC user will receive
withdrawnFromAdapteruint256Amount pulled from Yield Source to cover shortage

burn

Burn plDXY-BEAR and plDXY-BULL tokens to redeem USDC collateral.

function burn(
    uint256 amount
) external nonReentrant;

Parameters

NameTypeDescription
amountuint256The amount of token pairs to burn (18 decimals).

_withdrawFromAdapter

Withdraws USDC from yield adapter with redeem fallback.

function _withdrawFromAdapter(
    uint256 amount
) internal;

Parameters

NameTypeDescription
amountuint256USDC amount to withdraw (6 decimals).

triggerLiquidation

Locks the protocol into liquidated state when price >= CAP.

Permissionless. Prevents system revival if price drops after breach.

function triggerLiquidation() external nonReentrant;

emergencyRedeem

Emergency redemption when protocol is liquidated (price >= CAP).

Only burns plDXY-BEAR tokens at CAP price. plDXY-BULL becomes worthless.

function emergencyRedeem(
    uint256 amount
) external nonReentrant;

Parameters

NameTypeDescription
amountuint256The amount of plDXY-BEAR tokens to redeem (18 decimals).

ejectLiquidity

Emergency exit: withdraws all funds from yield adapter.

Bypasses timelock. Auto-pauses protocol. Use if adapter is compromised.

function ejectLiquidity() external onlyOwner;

withdrawFromAdapter

Withdraws a specific amount from yield adapter while paused.

Requires protocol to be paused. Use for gradual liquidity extraction when full ejectLiquidity() fails due to adapter liquidity constraints.

function withdrawFromAdapter(
    uint256 amount
) external nonReentrant onlyOwner;

Parameters

NameTypeDescription
amountuint256Desired USDC amount to withdraw. Capped by adapter’s maxWithdraw.

deployToAdapter

Deploys excess local USDC to the yield adapter.

Permissionless keeper function. Pushes USDC above the 10% buffer target into the adapter. Returns 0 silently when nothing to deploy (keeper-friendly).

function deployToAdapter() external nonReentrant whenNotPaused returns (uint256 deployed);

Returns

NameTypeDescription
deployeduint256Amount of USDC deployed to the adapter.

_deployExcess

Pushes local USDC above the 10% buffer target into the yield adapter.

function _deployExcess() internal;

previewHarvest

Previews yield harvest amounts and eligibility.

function previewHarvest()
    external
    view
    returns (
        bool canHarvest,
        uint256 totalSurplus,
        uint256 callerReward,
        uint256 treasuryShare,
        uint256 stakingShare
    );

Returns

NameTypeDescription
canHarvestboolTrue if surplus exceeds MIN_SURPLUS_THRESHOLD.
totalSurplusuint256Available surplus (total assets - liabilities).
callerRewarduint256Caller incentive (0.1% of harvest).
treasuryShareuint256Treasury allocation (20% of remaining).
stakingShareuint256Staking allocation (80% of remaining).

harvestYield

Permissionless yield harvesting with automatic redeployment.

Pays surplus from local buffer first, only hits adapter for the remainder. After distribution, deploys any remaining excess to the adapter. Distributes: 0.1% to caller, 20% of remaining to treasury, 80% of remaining to staking.

function harvestYield() external nonReentrant whenNotPaused;

_checkLiveness

Enforces 7-day cooldown after unpause for governance actions.

function _checkLiveness() internal view;

proposeFeeReceivers

Propose new fee receiver addresses (7-day timelock).

function proposeFeeReceivers(
    address _treasury,
    address _staking
) external onlyOwner;

Parameters

NameTypeDescription
_treasuryaddressNew treasury address.
_stakingaddressNew staking address (can be zero to send all to treasury).

finalizeFeeReceivers

Finalize pending fee receiver change after timelock expires.

function finalizeFeeReceivers() external onlyOwner;

proposeAdapter

Propose a new yield adapter (7-day timelock).

function proposeAdapter(
    address _newAdapter
) external onlyOwner;

Parameters

NameTypeDescription
_newAdapteraddressAddress of the new ERC4626-compliant adapter.

finalizeAdapter

Finalize adapter migration after timelock. Migrates all funds atomically.

function finalizeAdapter() external nonReentrant onlyOwner;

pause

Pause the protocol. Blocks minting and harvesting.

function pause() external onlyOwner;

unpause

Unpause the protocol. Starts 7-day governance cooldown.

function unpause() external onlyOwner;

rescueToken

Rescue accidentally sent tokens. Cannot rescue core assets.

function rescueToken(
    address token,
    address to
) external onlyOwner;

Parameters

NameTypeDescription
tokenaddressThe ERC20 token to rescue.
toaddressThe recipient address.

currentStatus

Returns the current protocol lifecycle status.

function currentStatus() external view override returns (Status);

Returns

NameTypeDescription
<none>StatusThe current Status enum value (ACTIVE, PAUSED, or SETTLED).

getSystemStatus

Returns comprehensive system metrics for dashboards.

function getSystemStatus() external view returns (SystemStatus memory status);

Returns

NameTypeDescription
statusSystemStatusStruct containing price, collateral ratio, and liquidity data.

_getTotalLiabilities

Calculates total liabilities based on BEAR supply at CAP price.

function _getTotalLiabilities() internal view returns (uint256);

_getTotalAssets

Calculates total assets (local USDC + adapter value).

function _getTotalAssets() internal view returns (uint256);

_requireSolventIfPaused

Reverts if paused and insolvent (assets < liabilities).

function _requireSolventIfPaused() internal view;

_getOraclePrice

Oracle price validation using OracleLib.

function _getOraclePrice() internal view returns (uint256);

Events

Minted

event Minted(address indexed user, uint256 amount);

Burned

event Burned(address indexed user, uint256 amount);

AdapterProposed

event AdapterProposed(address indexed newAdapter, uint256 activationTime);

AdapterMigrated

event AdapterMigrated(address indexed oldAdapter, address indexed newAdapter, uint256 transferredAmount);

LiquidationTriggered

event LiquidationTriggered(uint256 price);

EmergencyRedeemed

event EmergencyRedeemed(address indexed user, uint256 amount);

YieldHarvested

event YieldHarvested(uint256 totalSurplus, uint256 treasuryAmt, uint256 stakingAmt);

FeesProposed

event FeesProposed(address indexed treasury, address indexed staking, uint256 activationTime);

FeesUpdated

event FeesUpdated(address indexed treasury, address indexed staking);

EmergencyEjected

event EmergencyEjected(uint256 amountRecovered);

DeployedToAdapter

event DeployedToAdapter(address indexed caller, uint256 amount);

AdapterWithdrawn

event AdapterWithdrawn(uint256 requested, uint256 withdrawn);

TokenRescued

event TokenRescued(address indexed token, address indexed to, uint256 amount);

Errors

Splitter__ZeroAddress

error Splitter__ZeroAddress();

Splitter__InvalidCap

error Splitter__InvalidCap();

Splitter__ZeroAmount

error Splitter__ZeroAmount();

Splitter__ZeroRefund

error Splitter__ZeroRefund();

Splitter__AdapterNotSet

error Splitter__AdapterNotSet();

Splitter__LiquidationActive

error Splitter__LiquidationActive();

Splitter__NotLiquidated

error Splitter__NotLiquidated();

Splitter__TimelockActive

error Splitter__TimelockActive();

Splitter__InvalidProposal

error Splitter__InvalidProposal();

Splitter__NoSurplus

error Splitter__NoSurplus();

Splitter__GovernanceLocked

error Splitter__GovernanceLocked();

Splitter__InsufficientHarvest

error Splitter__InsufficientHarvest();

Splitter__AdapterWithdrawFailed

error Splitter__AdapterWithdrawFailed();

Splitter__Insolvent

error Splitter__Insolvent();

Splitter__NotPaused

error Splitter__NotPaused();

Splitter__CannotRescueCoreAsset

error Splitter__CannotRescueCoreAsset();

Splitter__MigrationLostFunds

error Splitter__MigrationLostFunds();

Splitter__InvalidAdapter

error Splitter__InvalidAdapter();

Splitter__PermitFailed

error Splitter__PermitFailed();

Structs

FeeConfig

struct FeeConfig {
    address treasuryAddr;
    address stakingAddr;
}

SystemStatus

struct SystemStatus {
    uint256 currentPrice;
    uint256 capPrice;
    bool liquidated;
    bool isPaused;
    uint256 totalAssets; // Local + Adapter
    uint256 totalLiabilities; // Bear Supply * CAP
    uint256 collateralRatio; // Basis points
    uint256 adapterAssets; // USDC value held in yield adapter
}

SyntheticToken

Git Source

Inherits: ERC20, ERC20Permit, ERC20FlashMint

Title: SyntheticToken

ERC20 token with flash mint and permit capability, controlled by SyntheticSplitter.

Used for plDXY-BEAR and plDXY-BULL tokens. Only the Splitter can mint/burn. Inherits ERC20FlashMint for fee-free flash loans used by routers.

Note: security-contact: contact@plether.com

Constants

SPLITTER

The SyntheticSplitter contract that controls minting and burning.

address public immutable SPLITTER;

Functions

onlySplitter

Restricts function access to the Splitter contract only.

modifier onlySplitter();

constructor

Creates a new SyntheticToken.

constructor(
    string memory _name,
    string memory _symbol,
    address _splitter
) ERC20(_name, _symbol) ERC20Permit(_name);

Parameters

NameTypeDescription
_namestringToken name (e.g., “Plether Dollar Index Bear”).
_symbolstringToken symbol (e.g., “plDXY-BEAR”).
_splitteraddressAddress of the SyntheticSplitter contract.

mint

Mint tokens to an address. Only callable by Splitter.

function mint(
    address to,
    uint256 amount
) external onlySplitter;

Parameters

NameTypeDescription
toaddressRecipient address.
amountuint256Amount to mint.

burn

Burn tokens from an address. Only callable by Splitter.

function burn(
    address from,
    uint256 amount
) external onlySplitter;

Parameters

NameTypeDescription
fromaddressAddress to burn from.
amountuint256Amount to burn.

Errors

SyntheticToken__Unauthorized

Thrown when a non-Splitter address attempts to mint or burn.

error SyntheticToken__Unauthorized();

SyntheticToken__ZeroAddress

Thrown when zero address provided for splitter.

error SyntheticToken__ZeroAddress();

VaultAdapter

Git Source

Inherits: ERC4626, Ownable2Step, IYieldAdapter

Title: VaultAdapter

ERC4626-compliant wrapper that deposits into a Morpho vault for yield.

Interchangeable with other yield adapters. Only accepts deposits from SyntheticSplitter.

Note: security-contact: contact@plether.com

Constants

VAULT

Morpho vault (ERC4626) that generates yield.

IERC4626 public immutable VAULT;

SPLITTER

SyntheticSplitter authorized to deposit.

address public immutable SPLITTER;

Functions

constructor

Deploys adapter targeting a Morpho vault.

constructor(
    IERC20 _asset,
    address _vault,
    address _owner,
    address _splitter
) ERC4626(_asset) ERC20("Vault Yield Wrapper", "vyUSDC") Ownable(_owner);

Parameters

NameTypeDescription
_assetIERC20Underlying asset (USDC).
_vaultaddressMorpho vault address (must have same underlying asset).
_owneraddressAdmin address for rescue operations.
_splitteraddressSyntheticSplitter authorized to deposit.

maxWithdraw

Maximum USDC withdrawable by owner.

Does not cap by VAULT.maxWithdraw() — Morpho Vault V2 returns 0 for all max* functions due to its gate system. Actual liquidity is enforced at withdrawal time.

function maxWithdraw(
    address owner
) public view override returns (uint256);

maxRedeem

Maximum adapter shares redeemable by owner.

See maxWithdraw for rationale on not delegating to vault.

function maxRedeem(
    address owner
) public view override returns (uint256);

maxDeposit

Maximum USDC depositable.

See maxWithdraw for rationale on not delegating to vault.

function maxDeposit(
    address
) public view override returns (uint256);

maxMint

Maximum adapter shares mintable.

See maxWithdraw for rationale on not delegating to vault.

function maxMint(
    address
) public view override returns (uint256);

totalAssets

Returns total USDC value of this adapter’s vault position.

function totalAssets() public view override returns (uint256);

Returns

NameTypeDescription
<none>uint256Total assets held in the Morpho vault, converted from vault shares.

_deposit

Deposits assets to Morpho vault after ERC4626 share minting.

function _deposit(
    address caller,
    address receiver,
    uint256 assets,
    uint256 shares
) internal override;

Parameters

NameTypeDescription
calleraddressMust be SPLITTER.
receiveraddressReceiver of adapter shares.
assetsuint256Amount of USDC to deposit.
sharesuint256Amount of adapter shares minted.

_withdraw

Withdraws assets from Morpho vault before ERC4626 share burning.

function _withdraw(
    address caller,
    address receiver,
    address owner,
    uint256 assets,
    uint256 shares
) internal override;

Parameters

NameTypeDescription
calleraddressCaller requesting withdrawal.
receiveraddressReceiver of withdrawn USDC.
owneraddressOwner of adapter shares being burned.
assetsuint256Amount of USDC to withdraw.
sharesuint256Amount of adapter shares burned.

accrueInterest

No-op — Morpho vault accrues interest on underlying markets during deposit/withdraw.

View functions (totalAssets, convertToAssets) may lag by a few blocks of unaccrued interest across the vault’s markets. This is negligible for an actively-used vault and self-corrects on the next state-changing interaction.

function accrueInterest() external;

rescueToken

Recovers stuck tokens (excluding the underlying asset and vault shares).

function rescueToken(
    address token,
    address to
) external onlyOwner;

Parameters

NameTypeDescription
tokenaddressToken to rescue.
toaddressRecipient address.

claimRewards

Claims rewards from an external distributor (Merkl, URD, etc.).

Reward tokens land in this contract; use rescueToken() to extract them.

function claimRewards(
    address target,
    bytes calldata data
) external onlyOwner;

Parameters

NameTypeDescription
targetaddressDistributor contract to call.
databytesABI-encoded call data for the claim function.

Errors

VaultAdapter__OnlySplitter

Thrown when caller is not the SyntheticSplitter.

error VaultAdapter__OnlySplitter();

VaultAdapter__InvalidAddress

Thrown when a zero address is provided.

error VaultAdapter__InvalidAddress();

VaultAdapter__InvalidVault

Thrown when vault’s underlying asset doesn’t match this adapter’s asset.

error VaultAdapter__InvalidVault();

VaultAdapter__CannotRescueUnderlying

Thrown when attempting to rescue the underlying asset.

error VaultAdapter__CannotRescueUnderlying();

VaultAdapter__CannotRescueVaultShares

Thrown when attempting to rescue vault share tokens.

error VaultAdapter__CannotRescueVaultShares();

VaultAdapter__CallFailed

Thrown when a reward claim call fails.

error VaultAdapter__CallFailed();

VaultAdapter__ForbiddenTarget

Thrown when claimRewards targets a forbidden address.

error VaultAdapter__ForbiddenTarget();

ZapRouter

Git Source

Inherits: FlashLoanBase, Ownable2Step, Pausable, ReentrancyGuard

Title: ZapRouter

Efficient router for acquiring plDXY-BULL tokens using flash mints.

Primary path: flash mints plDXY-BEAR → swaps to USDC via Curve → mints pairs → keeps plDXY-BULL. Fallback (direct) path: when BEAR is overpriced on Curve and the flash path can’t close, mints pairs with user USDC → sells all BEAR on Curve → sends BULL + USDC refund to user. For plDXY-BEAR, users should swap directly on Curve instead.

Note: security-contact: contact@plether.com

Constants

MAX_SLIPPAGE_BPS

Maximum allowed slippage in basis points (1% = 100 bps).

uint256 public constant MAX_SLIPPAGE_BPS = 100;

SAFETY_BUFFER_BPS

Safety buffer for flash loan repayment calculations (0.5% = 50 bps).

uint256 public constant SAFETY_BUFFER_BPS = 50;

USDC_INDEX

USDC index in the Curve USDC/plDXY-BEAR pool.

uint256 public constant USDC_INDEX = 0;

PLDXY_BEAR_INDEX

plDXY-BEAR index in the Curve USDC/plDXY-BEAR pool.

uint256 public constant PLDXY_BEAR_INDEX = 1;

SPLITTER

SyntheticSplitter contract for minting/burning pairs.

ISyntheticSplitter public immutable SPLITTER;

PLDXY_BEAR

plDXY-BEAR token (flash minted for swaps).

IERC20 public immutable PLDXY_BEAR;

PLDXY_BULL

plDXY-BULL token (output of zap operations).

IERC20 public immutable PLDXY_BULL;

USDC

USDC stablecoin.

IERC20 public immutable USDC;

CURVE_POOL

Curve pool for USDC/plDXY-BEAR swaps.

ICurvePool public immutable CURVE_POOL;

CAP

Protocol CAP price (8 decimals, oracle format).

uint256 public immutable CAP;

CAP_PRICE

CAP price scaled for Curve comparison (6 decimals).

uint256 public immutable CAP_PRICE;

ACTION_MINT

Flash loan action: mint plDXY-BULL.

uint256 private constant ACTION_MINT = 0;

ACTION_BURN

Flash loan action: burn plDXY-BULL.

uint256 private constant ACTION_BURN = 1;

Functions

constructor

Deploys ZapRouter with required protocol dependencies.

constructor(
    address _splitter,
    address _plDxyBear,
    address _plDxyBull,
    address _usdc,
    address _curvePool
) Ownable(msg.sender);

Parameters

NameTypeDescription
_splitteraddressSyntheticSplitter contract address.
_plDxyBearaddressplDXY-BEAR token address.
_plDxyBulladdressplDXY-BULL token address.
_usdcaddressUSDC token address.
_curvePooladdressCurve USDC/plDXY-BEAR pool address.

zapMint

Buy plDXY-BULL using USDC with flash mint efficiency.

For plDXY-BEAR, swap directly on Curve instead.

function zapMint(
    uint256 usdcAmount,
    uint256 minAmountOut,
    uint256 maxSlippageBps,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256The amount of USDC the user is sending.
minAmountOutuint256Minimum amount of plDXY-BULL tokens to receive.
maxSlippageBpsuint256Maximum slippage tolerance in basis points (e.g., 100 = 1%). Capped at MAX_SLIPPAGE_BPS (1%) to limit MEV extraction.
deadlineuint256Unix timestamp after which the transaction reverts.

zapMintWithPermit

Buy plDXY-BULL using USDC with a permit signature (gasless approval).

function zapMintWithPermit(
    uint256 usdcAmount,
    uint256 minAmountOut,
    uint256 maxSlippageBps,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
usdcAmountuint256The amount of USDC the user is sending.
minAmountOutuint256Minimum amount of plDXY-BULL tokens to receive.
maxSlippageBpsuint256Maximum slippage tolerance in basis points.
deadlineuint256Unix timestamp after which the permit and transaction revert.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_zapMintCore

function _zapMintCore(
    uint256 usdcAmount,
    uint256 minAmountOut,
    uint256 maxSlippageBps,
    uint256 deadline
) internal;

zapBurn

Sell plDXY-BULL tokens for USDC using flash mint efficiency.

function zapBurn(
    uint256 bullAmount,
    uint256 minUsdcOut,
    uint256 deadline
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
bullAmountuint256Amount of plDXY-BULL to sell.
minUsdcOutuint256Minimum USDC to receive (slippage protection).
deadlineuint256Unix timestamp after which the transaction reverts.

zapBurnWithPermit

Sell plDXY-BULL tokens for USDC with a permit signature (gasless approval).

function zapBurnWithPermit(
    uint256 bullAmount,
    uint256 minUsdcOut,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
bullAmountuint256Amount of plDXY-BULL to sell.
minUsdcOutuint256Minimum USDC to receive (slippage protection).
deadlineuint256Unix timestamp after which the transaction reverts.
vuint8Signature recovery byte.
rbytes32Signature r component.
sbytes32Signature s component.

_zapBurnCore

function _zapBurnCore(
    uint256 bullAmount,
    uint256 minUsdcOut,
    uint256 deadline
) internal;

onFlashLoan

ERC-3156 flash loan callback. Routes to mint or burn handler.

function onFlashLoan(
    address initiator,
    address,
    uint256 amount,
    uint256 fee,
    bytes calldata data
) external override returns (bytes32);

Parameters

NameTypeDescription
initiatoraddressAddress that initiated the flash loan (must be this contract).
<none>address
amountuint256Amount of plDXY-BEAR borrowed.
feeuint256Flash loan fee (always 0 for SyntheticToken).
databytesEncoded operation parameters.

Returns

NameTypeDescription
<none>bytes32CALLBACK_SUCCESS on successful execution.

onMorphoFlashLoan

Morpho flash loan callback - not used by ZapRouter.

Always reverts as ZapRouter only uses ERC-3156 flash mints.

function onMorphoFlashLoan(
    uint256,
    bytes calldata
) external pure override;

_handleMint

Executes mint operation within flash loan callback.

function _handleMint(
    uint256 loanAmount,
    uint256 fee,
    bytes calldata data
) internal;

Parameters

NameTypeDescription
loanAmountuint256Amount of plDXY-BEAR borrowed.
feeuint256Flash loan fee (always 0).
databytesEncoded mint parameters (action, user, usdcAmount, minSwapOut, minAmountOut, maxSlippageBps).

_handleBurn

Executes burn operation within flash loan callback.

function _handleBurn(
    uint256 loanAmount,
    uint256 fee,
    bytes calldata data
) internal;

Parameters

NameTypeDescription
loanAmountuint256Amount of plDXY-BEAR borrowed.
feeuint256Flash loan fee (always 0).
databytesEncoded burn parameters (action, user, bullAmount, minUsdcOut).

_zapMintDirect

Mints pairs, sells BEAR on Curve, sends BULL + USDC refund to user.

Used when the flash path can’t close (BEAR overpriced or high price impact).

function _zapMintDirect(
    uint256 usdcAmount,
    uint256 minAmountOut,
    uint256 maxSlippageBps
) private;

previewZapMint

Preview the result of a zapMint operation.

When flashAmount == 0, the direct path is used: expectedSwapOut is the USDC refund from selling minted BEAR, and totalUSDC equals usdcAmount (no flash leverage).

function previewZapMint(
    uint256 usdcAmount
)
    external
    view
    returns (
        uint256 flashAmount,
        uint256 expectedSwapOut,
        uint256 totalUSDC,
        uint256 expectedTokensOut,
        uint256 flashFee
    );

Parameters

NameTypeDescription
usdcAmountuint256The amount of USDC the user will send.

Returns

NameTypeDescription
flashAmountuint256Amount of plDXY-BEAR to flash mint (0 signals direct path).
expectedSwapOutuint256Expected USDC from swap (flash: contributes to minting; direct: refund to user).
totalUSDCuint256Total USDC for minting pairs (flash: user + swap; direct: user only).
expectedTokensOutuint256Expected plDXY-BULL tokens to receive.
flashFeeuint256Flash mint fee (0 for direct path).

previewZapBurn

Preview the result of a zapBurn operation.

function previewZapBurn(
    uint256 bullAmount
)
    external
    view
    returns (uint256 expectedUsdcFromBurn, uint256 usdcForBearBuyback, uint256 expectedUsdcOut, uint256 flashFee);

Parameters

NameTypeDescription
bullAmountuint256The amount of plDXY-BULL tokens to sell.

Returns

NameTypeDescription
expectedUsdcFromBurnuint256USDC received from burning pairs via Splitter.
usdcForBearBuybackuint256USDC needed to buy back plDXY-BEAR for flash loan repayment.
expectedUsdcOutuint256Net USDC the user will receive.
flashFeeuint256Flash mint fee (if any).

_estimateUsdcForBearBuyback

function _estimateUsdcForBearBuyback(
    uint256 bearAmount
) private view returns (uint256);

pause

Pause the router. Blocks zapMint and zapBurn.

function pause() external onlyOwner;

unpause

Unpause the router.

function unpause() external onlyOwner;

Events

ZapMint

Emitted when user acquires plDXY-BULL via zapMint.

event ZapMint(
    address indexed user,
    uint256 usdcIn,
    uint256 tokensOut,
    uint256 maxSlippageBps,
    uint256 actualSwapOut,
    uint256 usdcRefund
);

ZapBurn

Emitted when user sells plDXY-BULL via zapBurn.

event ZapBurn(address indexed user, uint256 tokensIn, uint256 usdcOut);

Errors

ZapRouter__ZeroAddress

error ZapRouter__ZeroAddress();

ZapRouter__ZeroAmount

error ZapRouter__ZeroAmount();

ZapRouter__Expired

error ZapRouter__Expired();

ZapRouter__SlippageExceedsMax

error ZapRouter__SlippageExceedsMax();

ZapRouter__SplitterNotActive

error ZapRouter__SplitterNotActive();

ZapRouter__InsufficientOutput

error ZapRouter__InsufficientOutput();

ZapRouter__SolvencyBreach

error ZapRouter__SolvencyBreach();

ZapRouter__PermitFailed

error ZapRouter__PermitFailed();