Trader Interactions

There are 4 possible trader actions on the protocol:

  1. Opening a position

  2. Extending a position (increasing the size of the position)

  3. Reducing a position (decreasing the size of the position)

  4. Closing a position

These 4 sequences of action are the same whether a position is LONG or SHORT.

Traders can only have 1 position open at a time per trading pair or market. For example, Alice can have a LONG position in the ETHUSD perpetual market and a SHORT in the BTCUSD market. But she can't have both a LONG and SHORT in the ETHUSD market because having a 100 USDC LONG position and a 50 USDC SHORT position would equal to a 50 USDC LONG position. In other words, the positions are aggregated for each market.

Action 1: Opening a position

Anyone with a allowlisted collateral token (e.g. USDC) can open a trading position in one of the perpetual markets with a call to the extendPosition function from the ClearingHouse contract.

Example A.1: Alice opens a LONG position in the ETHUSD trading pair. We assume a market price of 1000 ETHUSD.

  1. Alice deposits 1000 USDC (with the deposit function of ClearingHouse). 1000 USDC is deposited in Alice's vault (for this trading pair) and will be used as her collateral.

  2. Alice opens a 5x leveraged long position (with extendPosition in ClearingHouse). Her notional amount is 5000 USDC (1000 x 5).

  3. Increment mints 5000 vUSD and swaps this amount for 5 vETH. Increment registers 5000 vUSD debt and 5 vETH assets for the user position. Her position is registered as positionSize = 5 vETH and openNotional = -5000 vUSD.

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional. The amount is charged to the vault.

  5. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled. This mechanism helps mitigate the risk of flash loans manipulating the system.

  6. Insurance fee is taken from Alice's vault. At the time of writing, this value is 0.1% of the openNotional.

  7. The system checks that Alice's margin requirement is fulfilled. For a newly opened position, this means checking that the collateral is within the margin ratio requirement. The marginRatio is required to be at least 8%, and with a collateral of 1000 USDC, Alice's position is valid until openNotional surpasses an absolute value of -12500 USDC. The margin ratio of the position is derived from the value of the collateral, the value of its fundingPayments, and the profit/loss of the position at the close (i.e. price at position close - initial price). In summary, her notional amount of 5000 USDC passes the margin requirement test with a marginRatio of 20%. More details about margin here.

  8. Increment stores the current fundingRate for the user, which is the current funding rate on the market. This info will be used later on to determine the fundingPayments when closing (or reducing) the position, or when extending a position.

Example B.1: Bob opens a SHORT position in the ETHUSD trading pair, assuming a market price of 1000 ETHUSD.

  1. Bob deposits 1000 USDC (with the deposit function of ClearingHouse). 1000 USDC is deposited in Bob's vault balance and will be used as his collateral.

  2. Bob opens a 5x leveraged short position (with extendPosition in ClearingHouse). His notional amount is 5000 USDC (1000 x 5).

  3. Increment mints 5 vETH, and swaps them for 5000 vUSD. We register 5 vETH debt and 5000 vUSD assets for Bob position. His position is registered as positionSize = -5 vETH and openNotional = 5000 vUSD.

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional.

  5. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled. This mechanism helps mitigate the risk of flash loans manipulating the system.

  6. Insurance fee is taken from Bob's vault. At the time of writing, this value is 0.1% of the openNotional.

  7. The system checks that Bob's margin requirement is fulfilled. For a newly opened position, this means checking that the collateral is within the margin ratio requirement. The marginRatio is required to be at least 8%, and with a collateral of 1000 USDC, Bob's position is valid until openNotional surpasses an absolute value of -12500 USDC. In other words, her notional amount of 5000 USDC passes the margin requirement test with a marginRatio of 20%.

  8. Increment stores the current fundingRate for the user, which is the current funding rate on the market. This info will be used later on to determine the fundingPayments when closing (or reducing) the position, or when extending a position.

Action 2: Extending an existing position

When extending an existing position, traders may or may not deposit more collateral. If they don't deposit more collateral, their existing collateral will be used to determine if the margin requirement is met. If the margin requirement is not met with the new extended position, the collateral won't be accepted and the position will stay as it is.

To extend a position, traders need to call the same function as to open the position which is the extendPosition function in the ClearingHouse contract.

Example A.2: Continuing from Example A.1 above, Alice extends her LONG position in the ETHUSD trading pair with no extra collateral, essentially changing the leverage only.

  1. Alice calls extendPosition to make her existing LONG position of openNotional = -5000 vUSD and positionSize = 5 vETH larger (see Example A.1 above for the details of this position). She chooses not to provide additional collateral and she wants to double the notional size of her position. So she calls extendPosition with an amount of 5000e18 (remember amounts are in 18 decimals).

  2. Assuming the market price hasn't changed since Alice opened her position, Increment mints an extra 5000 vUSD and swaps them for 5 vETH. The system adds 5000 vUSD debt and 5 vETH assets to Alice position. Her trader position is now positionSize = 10 vETH and openNotional = -10,000 vUSD.

  3. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional.

  4. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled. This mechanism helps mitigate the risk of flash loans manipulating the system.

  5. Alice is debited from the funding payments on her previous trader position. In this case, Alice's funding rate will be computed based on the value of her previous position (positionSize of 5 vETH) and the funding rate stored at the time. The cost of the funding payments is reflected in Alice's collateral in the vault.

  6. 0.1% of Alice's added collateral is debited to the insurance reserve on the amount added to her position. In this case, it's on the 5000 extra notional amount, not the total value of 10,000 because she already paid an insurance fee for the first 5000.

  7. The system checks that Alice's margin requirement is fulfilled. With the margin ratio of 8% and collateral of 1000, Alice position is still valid (particularly in this hypothetical scenario, the market hasn't moved an inch in the meantime).

  8. Increment stores the new fundingRate for the user, which is the current funding rate on the market. This info will be used later on to determine the profit when closing (or reducing) the position, and when further extending a position.

Action 3: Reducing an existing position

Traders can reduce their existing positions by calling the reducePosition function in the ClearingHouse contract with the correct parameters.

Example A.3: Continuing from Example A.2 above, Alice wants to reduce her LONG position by half (current openNotional = -10,000 vUSD and positionSize = 10 vETH).

  1. Alice passes the reduction ratio as well as the proposedAmount in vETH which she wishes to sell from her positionSize asset. In this case, she simply wants to scale back her position by half from 10,000 to 5000 notional. So reductionRatio is 0.5 (or 5e17) and she passes a proposedAmount of 5. Computing proposedAmount is straightforward for LONG positions.

  2. The system checks that the proposedAmount isn't larger than the existing positionSize, which is indeed the case (4300 <= 8600).

  3. Increment mints 5 vETH and swaps them for 6000 vUSD, assuming the price of vETH has increased by 20% in the meantime.

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional. In our case that would be 6000 * 0.1% = 6.

  5. Increment computes the funding payments that Alice should pay or receive on the position size that she is selling. It's done using the funding rate that she got from the market at the time she last extended her position and using the current market funding rate and the size of the positionSize she is reducing. Let's say that would be -500.

  6. The profit is calculated from 1) the vUSD proceeds of the swap (+6000 because vUSD is equivalent to USDC in this market), 2) the funding payments (-500), 3) trading fees (-6) and 4) 50% of the notional value of her position (i.e. here -5000). In this case, her profit would be 494 (6000 - 500 - 5000 - 6).

  7. The system checks that the magnitude of the swap (step 3) in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled. This mechanism helps mitigate the risk of flash loans manipulating the system.

  8. The system adjusts Alice's position. positionSize moves from 10 to 5. openNotional moves from -10,000 to -4000. Note: the position isn't closed because Alice's positionSize is not 0.

  9. Increment settles the 494 USDC profit (or technically in UA, but UA is 1-to-1 for USDC in this case) in Alice's vault, whereby increasing her balance from 1000 to 1494 (a sweet move for Alice!).

If Alice had provided a collateral different than USDC, her profit would still have been accounted for in UA. For example, if she had provided 1000 DAI earlier (instead of 1000 USDC), she would have ended with her 1000 DAI collateral as well as a positive balance of 494 UA. For more details on the main accounting token of the protocol, see UA

Example B.2: Continuing from Example B.1 above, Bob wants to reduce his SHORT position by 30% (current openNotional = 5000 vUSD and positionSize = -5 vETH).

  1. Bob passes the reduction ratio as well as the proposedAmount in vUSD which represents the amount of vUSD needed to buy back 30% of the vETH debt that he owes (SHORT position means he has debt in vETH to the protocol). In this case, he wants to scale down his position by 30% from 5000 notional to 3500, so reductionRatio is 0.3 (3e17). To find the value for passing proposedAmount is a bit more trickier for SHORT positions than LONG positions. One way for Bob to approximate this value is to call getExpectedVBaseAmount until he gets an amount equal or slightly larger than 30% of his short position (the absolute value of positionSize) See how to choose proposedAmount for an in-depth explanation. In the case of this example, assuming that the price of vETH increased in the market, Bob buys back 30% of the vETH debt (which is equal to 1.5 vETH) and costs about 2000 vUSD (instead of the 1500 vUSD if the market remained like it was when Bob opened the position).

  2. The system checks that the proposedAmount isn't deviating more than 50% of the average market price in the past 15min (to avoid exploit).

  3. Increment mints 2000 vUSD and swaps them for 1.5 vETH (we assume here that 2000 vUSD is the right amount to buy back 30% of the positionSize).

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional. That is 0.1% * 2000 = 2.

  5. Increment computes the funding payments that Bob should pay or receive on the position size he's selling. It's done using the funding rate he got from the market at the time of opening his position, the current market funding rate, and the size of the positionSize he's buying back. In this case, let's say the funding rate is +300.

  6. The profit is calculated from 1) the vUSD proceeds of the swap (-2000 vUSD), 2) the funding payments (+300) 3) the trading fees (-2) and 4) 30% of the notional value of his position (i.e. here +1500). In this case, his profit would be -202, which means he made a loss.

  7. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled.

  8. Increment adjusts Bob's position. positionSize moves from 5 to 3.5 and openNotional moves from -5000 to -3000. Note that the position isn't closed yet because the absolute value of Bob's positionSize is still greater than 0.

  9. Increment settles the -202 profit in Bob's vault, whereby decreasing it from 1000 to 798 USDC.

If Bob had provided a collateral different than USDC, his loss would still have been accounted for in UA. For example, if he had provided 1000 DAI earlier (instead of 1000 USDC), he would have ended with his 1000 DAI collateral as well as a debt of 202 UA. He would have had to pay back his 202 UA debt first to be able to withdraw his 1000 DAI collateral.

Action 4: Closing a position

It's important to note that closing a position is just a special case of reducing a position where the position is reduced by 100% of its previous value, thus the user flow is the same as chart above. When doing so, the trader position is closed for the trading pair considered.

As such, traders should call the same function as to reduce their positions on the market, i.e. the reducePosition function in the ClearingHouse contract with the correct parameters.

Example A.4: Continuing from the Example A.3 above, Alice closes her LONG position in the ETHUSD trading pair (current openNotional = -4000 and positionSize = 5).

  1. Alice wants to cash out from her entire position. So reductionRatio is 100% (or 1e18) and proposedAmount is 5 (i.e. all the positionSize).

  2. The system checks that the proposedAmount isn't larger than the existing positionSize, which is indeed the case (5 <= 5).

  3. Increment mints 5 vETH and swaps them for 4900 vUSD, according to a new market price where vETH appreciated again.

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is assumed to be 0.1% of the openNotional. That is 0.1% * 4000 = 4.9 ~= -5.

  5. Increment computes the funding payments, let's assume that it is -100.

  6. The profit is calculated from 1) the vUSD proceeds of the swap (+4900), 2) the funding payments (-100), 3) the trading fees (-5) and 4) 100% of the notional value of her position (-4000). In this case, her profit would be 795.

  7. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled.

  8. Increment adjusts Alice's position. In this case, openSize changes to 0 which automatically closes Alice's position in this market.

  9. Increment settles the 795 profit in Alice's vault, whereby increasing it from 1500 to 2295 USDC.

As describe earlier, the profit is always accounted for in UA (regardless of the collateral the trader passes to satisfy the margin requirement). In this case, if Alice had provided 1000 USD worth of a supported collateral different than USDC (e.g. ETH), her combined profit would have provided her with a UA balance of 1295. She would then cash out her 1000 USD worth of collateral and her 1295 USDC profit.

Example B.3: Bob closes his SHORT position in the ETHUSD trading pair (continues from Example B.2 where openNotional = 3000 and positionSize = -3.5).

  1. Bob wants to close his position. So reductionRatio is 100% (or 1e18). The passing value for proposedAmount is still a bit more tricky to find. One way is to call getExpectedVBaseAmount until Bob gets an amount equal to or slightly bigger than 100% of his short position (i.e. the absolute value of positionSize). We assume that buying back 100% of the 3.5 vETH debt costs Bob 3500 vUSD.

  2. The system checks that the proposedAmount isn't deviating more than 50% of the average market price in the past 15min (to avoid exploit).

  3. Increment mints 3500 vUSD and swaps them for 3.5 vETH, if the proposedAmount in vUSD wasn't large enough Bob would be left with some of his SHORT position (even if reductionRatio was 100%).

  4. The trading fee is charged on the notional amount of the trade. At the time of writing the trading fee is is 0.1% of the openNotional. That is 0.1% * 3500 = 3.5.

  5. Increment computes the funding payments, let's assume that it is 301.

  6. The profit is calculated from 1) the vUSD proceeds of the swap (-3500), 2) the funding payments (+301), the trading fees (-3.5) and 4) 100% of the notional value of his position (+3000). In this case, his loss would be 202.5.

  7. The system checks that the magnitude of the swap in the ETHUSD trading pair must not exceed the maximum trade size per block. Otherwise, the transaction is cancelled.

  8. Increment adjusts Bob's position. His positionSize is now 0, which automatically closes his position on this trading pair market.

  9. Increment settles the 202.5 loss in Bob's vault, whereby increasing it from 798 to 595.5 USDC.

Traders with an open position wanting to move to the opposite position (e.g. from a SHORT position to a LONG position, and vice-versa) can do so in one go with the openReversePosition function.

Curve's CryptoSwap AMM sometimes generate "dust" during swaps. Dust describes very small amounts of market tokens that can't be swapped in the pool. These dust amounts are collected by the protocol and can be sold through governance.

Last updated