project screenshot 1
project screenshot 2
project screenshot 3
project screenshot 4

Palmcivet Perpetuals

Traders can open perpetual positions on Base, using liquidity on Arbitrum

Palmcivet Perpetuals

Created At

ETHGlobal Brussels

Winner of

Chainlink - Best use of Chainlink CCIP

Worldcoin - Pool Prize

Prize Pool

Project Description

This is a crosschain perpetuals protocol that allows traders to open positions on Base, using liquidity on Arbitrum. A trader's position can be long or short on the speculated index token. There are 5 key contracts in the system: The Vault and CCIPVaultManager contract on Arbitrum. The Positions, CCIPPositionsManager and AutomatedLiquidator on Base. The Vault on Arbitrum uses the ERC4626 standard. Liquidity providers are able to deposit and withdraw (although, they can NOT withdraw liquidity reserved for open positions in profit). The Positions contract on Base is how the trader interacts with the system to open positions, increase and decrease the size or collateral of their position. The respective crosschain manager contracts interact with the contracts on their own chain, and send messages and value across CCIP/CCTP to each other. Everytime liquidity is deposited or withdrawn, and everytime positions are managed, a message is sent across CCIP with this information, updating state on the other chain. Traders MUST provide collateral when opening a position. If the value of their position drops to such a degree that the maximum leverage threshold allowed by the protocol becomes violated, the AutomatedLiquidator will liquidate their position. The collateral and liquidity is in the form of Circle's USDC token. The price of the index token being speculated on is secured by combining Pyth and Chainlink pricefeeds. WorldID is used to mitigate abuse of the system by bots, allowing only unique WorldID users to open positions in the system.

Perpetuals are essentially just a way for a trader to bet on the price of a certain index token without actually buying the token while enabling the trader to employ leverage.

This Perpetuals Protocol allows traders to open, manage and close positions on Base, utilizing liquidity provided on Arbitrum via Chainlink CCIP. Traders must deposit collateral in the form of Circle's USDC to open a position. USDC is also the token deposited by liquidity providers.

Managing a position refers to increasing or decreasing the size or collateral of the position.

The entire protocol revolves around “positions” that belong to traders, a position is made up of the following:

  • Size - This is how much “virtual” capital a trader is commanding, the size of a BTC perpetual position might be 1.5 BTC. If the price of BTC goes up, the trader is able to realize the profits earned on the 1.5 BTC in their position.
  • Collateral - An amount of assets used to “back” a trader’s position, when trader’s lose money, their losses come out of the collateral. If the amount of collateral is deemed insufficient for the size of a position, the position is liquidated or force closed.

The size / collateral is the leverage of a position. E.g. if I open a position with $10,000 of USDC as collateral and a size of $20,000 of BTC, my leverage is 2x.

A profitable position can be kept open in perpetuity, whereas if the position's value drops to such a degree that the trader's collateral no longer sufficiently justifies their position, they will be automatically liquidated via Chainlink Automation. Liquidated collateral is added to the provided liquidity in the Vault, incentivising liquidity providers to potentially earn on their deposits.

There are two different directions a perpetual position can take.

  • Long → The trader profits when the price of the index token goes up, and loses when the price of the index token go down.
  • Short → The trader profits when the price of the index token goes down, and loses when the price of the index token goes up.

It is possible for any external address to liquidate an eligible position, receiving a liquidation bonus of 20% of any remaining collateral. However it is unlikely for external liquidators to execute liquidations before the AutomatedLiquidator.

Chainlink and Pyth pricefeeds are combined to get an average price of the asset being speculated on.

Positions can only be opened by users with unique Worldcoin IDs. Open positions are limited to one per WorldID. This is to mitigate manipulation of the system by bots.

Open interest is the measure of the aggregate size of all open positions.

Liquidity Providers are unable to withdraw liquidity reserved for profitable positions.

Liquidity reserves are necessary such that at all times there are enough assets in the liquidity pool (provided by liquidity providers) to pay out the profits for positions.

If there is only 10 USDC of liquidity deposited by liquidity providers, then allowing a trader to open a perpetual contract with $10,000 of size would be irresponsible. If the price moves even a little bit in the trader’s direction they will be more than $10 in profit, yet there will not be enough USDC to pay them out.

Similarly to increasing the size of a position, traders have the ability to decrease the size of their position, this includes closing their position (decreasing the size to 0).

However, decreasing a position is slightly more involved, we need to consider the PnL of the trader’s position when we are decreasing it.

If we don’t account for a trader’s PnL and allow them to decrease their size, they could manipulate their PnL and avoid paying losses! Additionally, decreasing the PnL this way reduces the probability that a trader will unexpectedly change the leverage of their remaining position drastically.

The realizedPnL is deducted from the position’s USDC collateral if it is a loss, and paid out to the trader in Circle's USDC token if it is a profit.

This way, if a trader decreases their position’s size by 50%, they realize 50% of their PnL.

And if a trader closes their position (e.g. decreases by 100% of the size), they realize 100% of their PnL.

If a trader decreases the size of their position to 0, the position is considered closed and the remaining collateral (after losses) is sent back to the trader.

Automation nodes are used to loop through the positions, checking for any that have exceeded the maximum leverage threshold, liquidating the ones that have violated this threshold based on pricefeed data, and the size and collateral of the position.

If the AutomatedLiquidator receives a liquidation bonus (20% of any remaining collateral), this value will compound, eventually using Chainlink Automation to swap the USDC for LINK via Uniswap V4 (although I didn't finish this part), and funding the Automation subscription, thus being self-sufficient.

This contract is automatically registered with Automation on deployment.

What makes a position liquidatable?

A position becomes liquidatable when its collateral is deemed insufficient to support the size of position that is open.

For our implementations we will use a leverage check to define whether a position is liquidatable or not:

leverage = size / collateral

Leverage is simply the ratio of the position’s size to the position’s collateral. The MAXIMUM_LEVERAGE is the cutoff point for the maximum leverage a position can have before it is considered liquidatable.

During liquidation, a position is force closed so that the protocol can remain solvent.

Traders are the actors opening perpetual positions and betting on the price of the index token.

Traders profit when the price of the index token moves in the direction they predict, and lose when it moves in the direction opposite to what they predict.

Traders must provide collateral for their position, the collateral is used to cover their losses in the event that price moves in the opposite direction of what they predicted.

Liquidity providers take the opposite side of traders, they stand to profit when traders lose money or are liquidated.

Liquidity providers provide the assets that are used to pay out profit for traders. When a trader profits they get tokens from the liquidity providers. When a trader loses, they pay tokens to the liquidity providers out of their position’s collateral.

How it's Made

The project was built in Foundry/Solidity. Chainlink CCIP was used for crosschain messaging, with CCTP under the hood for crosschain USDC transfers. Arbitrum and Base chains were used. Pyth and Chainlink oracles were combined to get the price of the underlying, speculated index token. WorldID was used to mitigate abuse by bots. Chainlink's local CCIP simulator was used for testing.

background image mobile

Join the mailing list

Get the latest news and updates