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

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;
}