Funding tick

Overview of a funding tick

Funding payments are part of the business logic of a perpetual application. A funding tick is a mechanism to credit or debit the collateral in a user’s position, according to predefined logic, in order to incentivize certain strategies, and to keep the prices in the exchange for synthetic assets as close as possible to prices outside of the system.

When StarkEx applies a funding tick, the StarkEx system credits or debits the collateral in a position, in StarkEx units of a synthetic asset.

Funding ticks occur in a StarkEx Perpetual Trading system regularly, but StarkEx applies funding ticks to a position only when a transaction affects the value of the position, such as when the owner executes a trade or when another user transfers funds to the position. If multiple funding ticks have occurred since the last such transaction, StarkEx cumulatively applies all these funding ticks.

When a funding tick occurs, a position’s balance changes based on the global funding index.

The operator can apply a funding tick even when StarkEx doesn’t, such as when a user queries a position without actually executing a transaction. Such a case can cause problems with state synchronization. For more information, see Funding ticks and state synchronization

Since StarkEx already supports periodic modification of users' balances, this support can be easily extended for different purposes, such as debt management or periodic rewards.

How a collateral change is calculated

The following calculation determines the amount of collateral in a position after a funding tick occurs:

\[\text{collateral}_\text{new} = \text{collateral}_\text{current} + ⌊-\frac{((\text{index}_\text{new} - \text{index}_\text{cached}) \cdot \text{amount_of_synthetic})}{2^{32}}⌋\]

Where \(\text{amount_of_synthetic}\) has the resolution factor applied.

Example of a funding tick

This example uses a transfer of 0 USDC in order to illustrate how a funding tick affects the amount of collateral in a position.

Although in a production system such a transfer is unlikely, it is useful for this example to show how a funding tick can affect a position’s collateral.

Consider the following:

  • Alice holds a position with:

    • 1,000,000 StarkEx units of USDC as collateral

    • 225,000,000 StarkEx units of ETH

  • The cached global funding index for ETH is 0.

  • The new global funding index for ETH is 0.009, which you send to the Gateway as 38654705. For more information on how this value is calculated, see Example: Calculating the global funding index to send to the StarkEx gateway.

A transfer of 0 USDC to Alice’s account occurs, updates Alice’s position, based on the new global funding index.

The amount of collateral in Alice’s vault is now updated according to the following calculation:

\[1,000,000 + ⌊-\frac{((38654705 - 0) \cdot 225,000,000)}{2^{32}}⌋\]

Notice that the rounded down expression returns -2,025,000, but if the position had -225,000,000 ETH instead of 225,000,000 ETH, the rounded down expression would return 2,024,999.

For information on calculating the global funding index for the StarkEx gateway, see Global funding indices.

Alice’s new position is:

  • -1,025,000 StarkEx units of USDC as collateral

  • 225,000,000 StarkEx units of ETH

Validity period

A funding index is valid for set time period. You can configure this period with the funding_validity_period configuration parameter. If a global funding index is no longer valid when you send a new funding tick, the StarkEx gateway sends a request for an alternative transaction.

A funding tick updates the system time. You, the operator, should supply funding indices such that they are always valid with respect to their validity period.

The funding tick flow

1. The operator sends a funding tick to StarkEx

The operator sends StarkEx funding ticks at a regular interval, at least once every twenty four hours, by calling the add_transaction API with the FundingTick transaction type. The API call specifies the exact date and time of the funding tick, in seconds since the Unix epoch, as well as a dictionary of global funding indices.

The operator defines the interval in the general configuration, and StarkWare approves it.

Although the minimum required frequency for sending funding ticks is once every twenty four hours, it is recommended to send them several times a day, or even more frequently, because perpetual systems have an internal system time that becomes increasingly unsynchronized with the StarkEx system as time passes. Funding ticks synchronize the system time.

Every type of asset in the system should have a corresponding global funding index, and every funding tick should include all active assets in the system.

You do not need to include a new asset that has never been included in a funding tick. But once you do, you must include it for all subsequent funding ticks.

2. StarkEx verifies the validity of a funding tick

StarkEx checks the following conditions:

  • The new system time is greater than the previous system time.

  • For every asset type, represented by asset_id, the following condition holds:

    \[|\text{prev_global_index} - \text{global_index}| \leq\ \text{config.max_funding_rate} \cdot (\text{system_time}-\text{prev_funding_time}) \cdot \text{current_price[asset_id]}\]

    Where config.max_funding_rate is an on-chain configuration parameter. For more details and how to calculate this value, see Global configuration. current_price is set according to the last oracle price tick, with the corresponding resolution factor applied. For more information, see Oracle price tick and Resolution.

    In the above formula, the time since the previous funding tick directly affects the change allowed by the funding tick. In order to limit the permitted change, StarkEx verifies the following at the beginning of every transaction:

    \[\text{system_time} - \text{prev_funding_time} \leq \text{funding_validity_period}\]

    For more information on funding_validity_period, see Global configuration

3. Funding tick effect

After the funding tick is accepted, an array called global_indices is updated with a new value for every type of asset.

The operator credits or debits the collateral in a position only when a transaction occurs that affects the position, such as when the owner executes a trade or when another user transfers funds to that position. So not every funding tick affects every user’s positions.

Each position stores a value called position_cached_indices for every type of synthetic asset. position_cached_indices represents the most recent funding tick that affected it.

The following transaction types affect positions:

The execution of a transaction consists of two steps:

  1. For every type of synthetic asset, reduce the funding debit from the balance and update the position indices, such that:

    The balance of a position, expressed in the collateral coin, is identical to

    \[\text{position_balances[asset_id]} \cdot (\text{global_indices[asset_id]} - \text{position_cached_indices[asset_id]})\]

    and

    \[\text{position_cached_indices[asset_id]}= \text{global_indices[asset_id]}\]
  2. Apply the transaction-specific logic.

If a transaction is invalid, the first step is executed nonetheless.

4. Batch validity checks

If the funding tick is valid, it is included in a batch to be submitted on-chain along with a validity proof. For more information on on-chain state updates, see State Update.

As part of the batch validity checks, the StarkEx contract checks that the most recent funding tick’s timestamp in the batch was within the last week. If not, the batch reverts, with the error SYSTEM_TIME_OUTDATED.

This limits the time between two funding ticks and thus limits the funding debits.

Implementing a funding tick

To send a funding tick, use the add_transaction API method with the FundingTick transaction type.

The StarkEx REST API reference includes all necessary information.