Aggregator/DeFi Integration

Crystal is a fully on-chain orderbook exchange. As a result, the output of a swap is not determined by any algorithm such as x*y = k, and quotes must either be simulated onchain or locally. The L2 book can be directly queried onchain with a single rpc method, while the L3 book is also fully onchain but must be queried manually. Every order placement, cancelation, and fill emit events that carry sufficient information to update a local copy of the L3 book.

A couple of variables are relevant in determining the behavior of a market:

  • quoteAsset: If this is the input asset, the action is a buy order.

  • baseAsset: If this is the input asset, the action is a sell order.

  • marketType: If the market type is 0, valid price ticks are defined as multiples of tickSize. Otherwise, price ticks are valid if they have five significant figures and are a multiple of tickSize.

  • tickSize: Price ticks must be a multiple of tickSize to be valid. In most markets, this will be set to 1.

  • maxPrice: The maximum (exclusive) price bound for a limit order.

  • minSize: The minimum valid size of a limit order, denominated in the quote asset.

  • takerFee: The taker fee paid by all market orders to the protocol. (100,000 - takerFee) / 10 is equivalent to the taker fee in basis points.

  • makerRebate: The maker rebate paid to the owner of a resting limit order. This fee is only paid on quantities filled against the orderbook. The total effective fee on a market order is takerFee + makerRebate. (100,000 - makerRebate) / 10 is equivalent to the taker fee in basis points.

  • reserveQuote: Quote asset reserve for the AMM.

  • reserveBase: Base asset reserve for the AMM.

It is recommended to retain a local copy of the L2 book in order to simulate quotes locally. To do this, the current state of the orderbook can be snapshotted with getPriceLevelsFromMid, and updates can be subscribed to via the ordersUpdated and Fill events. Alternatively, a polling-based approach can be used, where repeated snapshots could be taken every couple of seconds. Resting quantities are in denominated in their underlying asset, so in an ETH/USDC market where USDC is the quote asset, buy orders are represented in their USDC amount while sell orders are represented in their ETH amount.

Some pairs also have a backstop constant product AMM. To check whether a market has the AMM enabled, getMarket can be called or MarketCreated and MarketUpdated events can be subscribed to. The AMM reserves can be queried with getReserves, and a Sync event is emitted in place of a fill event when reserves are altered. Trades are routed to the best source of liquidity, following a procedure best simplified as:

  1. Check the price of the next limit order

  2. Check the AMM price

  3. If the AMM price is more competitive, fill the AMM until either the order quantity is exhausted or the marginal execution price is equal to the limit order price adjusted for maker rebates, whichever comes first

  4. If there is any remaining amount, fill the limit order

  5. Repeat if needed until the order quantity is exhausted or the slippage limit of the trade is hit

Majors and correlated pairs will have the AMM disabled, while markets graduated from our launchpad will primarily rely on the AMM liquidity until sufficient trading interest is reached. That said, a resting limit order could potentially give users a much better fill, so it is recommended to index/simulate the orderbook as well. If you would like to see the exact implementation of the AMM, please reach out to our team.

Alternatively, the getAmountsOut and getAmountsIn function on the exchange contract can be called to easily simulate quotes, but this is not recommended for aggregators. To directly simulate a quote on an individual market, the getQuote method can also be called with the option to set a slippage limit, or price point at which the quote terminates and the filled portion is returned.

To conduct a trade, it is recommended to directly call marketOrder on the exchange contract with the specified market. To participate in our fee sharing program, pass an address controlled by the team operating the integration as the referrer parameter in order to recieve a fee commission. Any referral earnings can be claimed onchain anytime through the Crystal interface, and no creation of a referral link is necessary.

If you have any questions or would like to notify our team that you plan on integrating Crystal, please contact our team through our Discord.

Last updated