MarginEngine
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
| Name | Type | Description |
|---|---|---|
seriesId | uint256 | |
roundHints | uint80[] | 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;
}