Carbon DEX
Our solution for trading carbon is a decentralized exchange for tokenized carbon credits. Blockchain allows us to store credits on-chain, increase transparency, accessibility and openness. Now everyone will be able to buy, trade, and retire carbon credits. We're bringing a range of different credits under one roof for our Carbon DEX: your one-stop-shop for tokenized carbon credits.
Likvidi CarbonDEX is a non-custodial semi-decentralized carbon token exchange for trading ERC-20 compatible voluntary market carbon credits. It combines a centralized order book and order matching engine with a trustless ledger kept in an Ethereum smart contract to achieve fast performance and smooth user experience.
Currently there are no carbon credit exchanges for tokenized carbon credits. Carbon credits can be traded in AMM type DEX's such as Uniswap and Sushiswap, but the problem is that they require large amounts of liquidity in the pools to enable trading without too high slippage. With our exchange solution we make it easier to trade carbon credits without need to provide too much liquidity.

Technical overview

The exchange consists of the following parts:
  1. 1.
    An Ethereum smart contract that stores ERC-20 tokens (stablecoins and carbon credits) on behalf of the user and can execute trades with signed consent from the user.
  2. 2.
    A centralized backend that stores the order book, keeps a record of user balances and can submit trades on the blockchain.
  3. 3.
    An API that the user uses to interact with the backend.
Semi-decentralized means that the order books are centralized, but otherwise the exchange is non-custodian. With centralized order books the exchange is more gas efficient and faster order matching process.
We aim to list a wide range of high quality carbon credits from different methodologies. We are first focusing on forestry and agriculture based carbon credits. All carbon credits on our exchange are verified by a reputable third party carbon credit verifier.
All carbon credits that get listed on the exchange will go through Likvidi’s internal vetting process, where Likvidi completes full due diligence to ensure that the credits can be considered high quality. We focus on mainly listing carbon credit projects that have vintage up to 6 years old and are part of Climate, Community & Biodiversity (CCB).
The first problem with order book model DEX is gas fees. People would lose money if they have to pay gas fees every time they place orders. In our exchange Likvidi pays the gas fees on behalf of the user, so the user doesn’t have to pay the gas fees when placing orders or canceling orders. Constantly adjusting orders doesn’t cost anything for the end user - the end user only pays gas fees when they deposit or withdraw funds from the exchange smart contract.

Flow of assets

User funds (stablecoins such as USDC and carbon credits) are stored in a smart contract in the Ethereum blockchain. The user deposits the funds from their Ethereum wallet to the smart contract, which keeps an internal ledger of individual user balances. The user can later withdraw their balances according to the ledger. When trades are made, only this internal ledger is updated.
Fiat money deposited via fiat onramps (such as Wyre that we use) is received as USDC stablecoin.


To trade carbon credits in the exchange, the user must first deposit USDC stablecoin or carbon credits to the smart contract. To do that, the user sends a transaction to the smart contract. For ERC20 tokens, the user must first call the approve function of the token contract, allowing the exchange contract to spend the desired amount of tokens on the user’s behalf. When the deposit is done, the backend polls the balance from the smart contract and updates balances stored on server-side.


To get the carbon tokens or stablecoins back to their Ethereum wallet, the user must withdraw them from the smart contract. Users can do the withdrawal on our platform through the API, which verifies that the user holds the required balance and that the balance is not locked in open orders, and then initiates the withdrawal from the smart contract using an admin-only function call.
However, to maintain the non-custodial aspect of the exchange even in the case where the exchange backend is not available, it is also possible to withdraw the tokens or Ether directly from the smart contract. Because it is important that the backend has the chance to cancel all open orders before they get matched, this withdrawal process is two-phased:
  1. 1.
    First, the user calls a function to tell that they want to withdraw N amount of token T. This causes the smart contract to store the current timestamp and to emit an event to which the backend can react.
  2. 2.
    After a predetermined amount of time (e.g. 24 hours) has passed, the user can call another function to actually withdraw the tokens or Ether.

Submitting orders

Orders are submitted using the API. Before submitting the order, the user must sign it using their Ethereum wallet. By signing the order, the user grants the exchange contract the permission to execute it either fully or partially at its specified price or better. That means that a buy order with price 2 / 1 could be executed at the price 3 / 2 (lower price, so better) whereas a sell order with 2 / 1 could be executed at the price 3 / 1 (higher price, so better), but not vice versa. This is enforced both in the backend and in the smart contract.
By specifying prices as fractions, we can be sure that no rounding errors occur when executing trades as long as both price denominators in a trade can divide both amounts. This restriction is enforced in the smart contract. In practice, the backend will enforce a lot size, which is the minimum quantity in which amounts can be specified (such as 1 000 000 000 base units), and will only accept orders in which amount is divisible by the lot size and in which the lot size is divisible by the fee denominator.

Order Execution

When an order is submitted, it is validated on the backend and put in a queue, from where the orders get processed one at a time.
When processing the order, the backend tries to match it against existing orders in the order book. Matching is done for both limit and market orders. Matching happens first on the backend, and during it orders get updated in the order book and balances stored on the backend get updated. Afterwards, trades get queued to be executed in the blockchain.
If the submitted order was a limit order and was not fully filled during the matching process, it gets submitted (possibly in a partially filled state) to the order book.
Market orders get either executed fully or not at all (fill-or-kill).


When a new order is submitted to the exchange, it is matched against existing orders. The matching algorithm works as follows:
  1. 1.
    Get a list of existing limit orders that are fillable and have the same base/quote token pair and the direction opposed to the newly-submitted order from the order book DB.
  2. 2.
    Sort the order list first by price (ascending for buys, descending for sells) and second by creation timestamp.
  3. 3.
    Get the first fillable order of the list. Check if the price is better (higher for buys, lower for sells) than the price of the newly-submitted order. If not, stop matching.
  4. 4.
    If the price is better, fill the orders according to the following specs:
    1. 1.
      Price is the price of the newly-submitted order
    2. 2.
      Amount is the lowest amount fillable of the new orders
  5. 5.
    After step 4, either the newly-submitted order or the order from the DB (or both) gets fully filled. If the newly-submitted order got fully filled, stop matching. Otherwise, repeat from step 3.

Blockchain trade execution

Trades are processed from the get sent from the trade queue to the blockchain in a backend process. The process sends them to the blockchain by transacting to the trade function of the smart contract. The function can only be called from pre-determined admin accounts.
Trades executed in the blockchain should always get executed identically to the trades on the backend during the matching process, and another background process verifies that this is indeed what happens. As such, the ledger on the blockchain can be thought of as a trustless ledger that mirrors the backend state with some delay.

Order cancellation

Order cancellation happens on the server side. After an API call is made with the correct authentication, the order gets marked as canceled in the DB.
Copy link
Technical overview
Flow of assets