Skip to main content

PositionManager

The PositionManager contract extends BasePositionManager with user-facing functionality for position management. It includes role-based access control for position execution and liquidation.

Contract Overview

The PositionManager handles:
  • Direct creation, modification, and liquidation of positions
  • Execution of orders from the OrderBook
  • Role-based access control for different operations
  • Integration with the OrderBook for limit orders
The PositionManager provides direct position execution functionality, as opposed to the queue-based approach of the PositionRouter.

Key Functions

Position Management

function increasePosition(
    address[] memory _path,
    address _indexToken,
    uint256 _amountIn,
    uint256 _minOut,
    uint256 _sizeDelta,
    bool _isLong,
    uint256 _price
) external;
Increases a position with the specified parameters.
function increasePositionETH(
    address[] memory _path,
    address _indexToken,
    uint256 _minOut,
    uint256 _sizeDelta,
    bool _isLong,
    uint256 _price
) external payable;
Increases a position using ETH as the input token.
function decreasePosition(
    address _collateralToken,
    address _indexToken,
    uint256 _collateralDelta,
    uint256 _sizeDelta,
    bool _isLong,
    address _receiver,
    uint256 _price
) external;
Decreases a position with the specified parameters.
function decreasePositionETH(
    address _collateralToken,
    address _indexToken,
    uint256 _collateralDelta,
    uint256 _sizeDelta,
    bool _isLong,
    address payable _receiver,
    uint256 _price
) external;
Decreases a position and receives ETH instead of WETH.

Liquidation

function liquidatePosition(
    address _account,
    address _collateralToken,
    address _indexToken,
    bool _isLong,
    address _feeReceiver
) external;
Liquidates a position if it meets the liquidation criteria.

Order Execution

function executeIncreaseOrder(
    address _account,
    uint256 _orderIndex,
    address payable _feeReceiver
) external;
Executes an increase order from the OrderBook.
function executeDecreaseOrder(
    address _account,
    uint256 _orderIndex,
    address payable _feeReceiver
) external;
Executes a decrease order from the OrderBook.

Access Control

The PositionManager implements several access control mechanisms:
function setOrderKeeper(address _account, bool _isActive) external;
Sets or removes an order keeper who can execute orders.
function setLiquidator(address _account, bool _isActive) external;
Sets or removes a liquidator who can liquidate positions.
function setPartner(address _account, bool _isActive) external;
Sets or removes a partner who can place orders for their users.
function setInLegacyMode(bool _inLegacyMode) external;
Sets the contract to legacy mode, which affects access control.

Validation

function setShouldValidateIncreaseOrder(bool _shouldValidateIncreaseOrder) external;
Sets whether increase orders should be validated before execution.
function shouldValidateIncreaseOrder() external view returns (bool);
Returns whether increase orders should be validated.

Integration with OrderBook

The PositionManager is tightly integrated with the OrderBook contract:
function setOrderBook(address _orderBook) external;
Sets the OrderBook contract address.
function orderBook() external view returns (address);
Returns the OrderBook contract address.

Security Considerations

The PositionManager implements several security features:
  • Role-Based Access Control: Different roles for order execution and liquidation
  • Price Validation: Ensures that positions are executed at reasonable prices
  • Integration Validation: Validates interaction with other contracts
  • Error Handling: Comprehensive error handling for various failure scenarios
Only approved liquidators can liquidate positions when in private liquidation mode.

Example Usage

1

Increasing a Position

A trader wants to open a 5x long ETH position with 1 ETH as collateral.
// Price to use for execution
const ethPrice = ethers.utils.parseUnits("2000", 30);

// Increase position parameters
await positionManager.increasePositionETH(
  [wethAddress], // Path (no token swap)
  wethAddress, // Index token (ETH)
  0, // Min output (no swap)
  ethers.utils.parseUnits("5", 30), // Size delta (5x leverage)
  true, // Is long
  ethPrice, // Price to use
  { value: ethers.utils.parseEther("1") } // 1 ETH as collateral
);
2

Decreasing a Position

Later, the trader wants to close half of the position.
// Price to use for execution
const ethPrice = ethers.utils.parseUnits("2100", 30);

// Decrease position parameters
await positionManager.decreasePositionETH(
  wethAddress, // Collateral token
  wethAddress, // Index token
  ethers.utils.parseEther("0.5"), // Withdraw half of the collateral
  ethers.utils.parseUnits("2.5", 30), // Size delta (half position size)
  true, // Is long
  userAddress, // Receiver
  ethPrice // Price to use
);
3

Executing an Order

An order keeper notices a pending increase order that meets its execution conditions.
// Order keeper executes the order
await positionManager.executeIncreaseOrder(
  userAddress, // Account that created the order
  0, // Order index
  keeperAddress // Fee receiver
);

Legacy Mode

The PositionManager includes a legacy mode feature:
function setInLegacyMode(bool _inLegacyMode) external;
In legacy mode, certain access control restrictions are relaxed, making the PositionManager backward compatible with earlier versions. This feature is typically used during protocol upgrades when necessary to maintain compatibility.
I