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

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
}