Smart Contract Integrations

You can find the deployed contract addresses here: Contracts

The following actions are useful when directly interacting with the markets. To make life easier, Perennial has built an Operator contract called: MultiInvoker which can be used to simplify/abstract much of this flow. See more about it here

Market Operations (Market.sol)

The following are common actions you might need to undertake to interact with an instance of a market contract.

Source code: here

Get a Market's Global Position

When interacting with a given market its useful to know the overall state. In order to find this you should call two functions: position() & global(). With these you can calculate things like open interest, skew, funding rate, interest rate etc.

  • Call position()

    • Returns

      • timestamp - The timestamp of the position

      • maker - The maker position size*

      • long - The long position size*

      • short - The short position size*

      • Notes

        • * - This is the aggregate value of all positions denominated in units of the Payoff function

  • Call global()

    • Returns:

      • pAccumulator - The current PAccumulator state

      • latestPrice - The latest valid price

Helpful calculations:

  • openInterestInUSD=(long+short)āˆ—latestPriceopenInterestInUSD = (long + short) * latestPrice

  • marketSkew=long/shortmarketSkew = long / short

  • Funding Rate - using pAccumulator

  • Interest Rate - using long , short & maker

Get an Account's Market Position

In order to read a particular account's position you can use the positions() function. This returns a similar object to the global position() call.

  • Call positions(address)

    • Returns

      • timestamp - The timestamp of the position

      • maker - The maker position size*

      • long - The long position size*

      • short - The short position size*

      • fee - The fee for the position^

      • keeper - The fixed settlement fee for the position^

      • collateral - The collateral at the time of the position settlement^

      • delta - The change in collateral during this position^

    • Notes

      • * The value of the position denominated in units of the Payoff function

      • ^ Only used for pending positions

Update Your Position (Make a Trade)

In each Market, there is an update() function which a user calls to modify their position. You can go long, short, make a market, deposit or withdraw collateral using this command.

  • Approve() DSU (collateral) on specific market

  • Call update()

    • Arguments:

      • account - The account to operate on

      • newMaker - The new maker position for the account*

      • newLong - The new long position for the account*

      • newShort - The new short position for the account*

      • collateral - The collateral amount to add or remove from the account^

      • protect - Whether to put the account into a protected status for liquidations

    • Notes:

      • * This is the absolute value of the position denominated in units of the Payoff function.

      • ^ Positive number to add collateral, negative to remove.

Calculating Available Liquidity:

When opening/closing a position the market is bound by available liquidity being provided by the Makers. In order to calculate this you can do the following:

  • Call position()

    • Returns

      • timestamp - The timestamp of the position

      • maker - The maker position size*

      • long - The long position size*

      • short - The short position size*

    • Notes

      • * - This is the aggregate value of all positions denominated in units of the Payoff function

  • Calculate Liquidity in USD

    • \begin{align*} liqMajor &= maker + \min(long, short) - \max(long, short) \\ liqMinor &= liqMajor + maker \end{align*}

      • Note: availableMajor equal whichever side has more open interest

  • Call global()

    • Returns:

      • latestPrice - The latest valid price

  • Calculate Liquidity in units of Payoff

    • liqUnits=liqMajor/latestPriceliqUnits = liqMajor / latestPrice

Confirming Position Update

Due to the delayed settlement flow of Perennial, while position updates are very likely to be settled there are rare cases where settlement might not occur. To check your position has been updated you can do the following:

  • Updated(account, context.currentTimestamp, ...) is emitted when you submit an updated().

  • Call Market.versions(timestamp) using the timestamp from the event.

    • Returns a struct with the property valid. If the value is true then your update was successful.

    • If the value is false, you can check to see if the timestamp from the Update() event is after the timestamp returned in the latest() call in Market's Oracle. If this is the case, the update() has failed and needs to be resubmitted.

Example Contract Integration: Vaults

The multi-market maker vault that is featured on the Perennial UI is a great example of a contract integration into the Perennial market contracts.

The vault is a standalone contract that acts as a normal user on configured markets. Whenever a user deposits into/withdraws from the vault contract it update the maker positions across the markets.

See the codebase here

Make sure to check out the Considerations section before building a direct integration!

Last updated