Matching Transaction
📖 Centuari Protocol — Transaction Matchmaking Documentation
Reference Implementation: CentuariCLOB.sol
📌 Overview
Centuari’s Central Limit Order Book (CLOB) module is designed to facilitate a decentralized, permissionless, and configurable matching engine between lenders and borrowers within isolated lending markets. Each market is uniquely identified by a MarketConfig
struct and associated with a dedicated DataStore contract, ensuring market data segregation and flexibility.
📌 Core Concepts
Order
A user-submitted request to lend or borrow a specific amount at a defined interest rate.
Side
Indicates whether the order is a LEND
or BORROW
.
Matchmaking
Process of pairing orders with complementary sides and compatible rates/amounts.
MarketConfig
Defines the loan asset, collateral asset, maturity date, and market-specific parameters.
DataStore
A per-market on-chain storage contract used to track orders, rates, collateral, and active status.
📌 Transaction Matchmaking Process
1️⃣ Order Placement: placeOrder
When a lender or borrower places an order:
Validate market status (
onlyActiveMarket
)If rate = 0 → fetch current market rate from
DataStore
Transfer tokens (loan asset for lenders, collateral for borrowers)
Build a new
Order
object with an auto-incremented order IDEmit
OrderPlaced
event
Code reference:
IERC20(config.loanToken).transferFrom(msg.sender, address(CENTUARI), amount);
...
Order memory newOrder = Order({
id: orderId,
trader: msg.sender,
...
});
2️⃣ Order Matching Loop
After placing, the order enters a loop attempting to match against existing open orders on the opposite side:
Fetch head of the opposite side’s linked list queue by rate
Skip incompatible, cancelled, filled, or self-trader orders
Determine
matchedAmount
(minimum of available amounts)Call
_matchOrder()
to execute the settlement logicUpdate remaining amounts, collateral, and order status
Continue looping until order fully filled or no match found
Code reference:
while (oppositeOrderId != 0 && newOrder.status != Status.FILLED) {
...
_matchOrder(...);
}
3️⃣ Order Storage on Partial Fill
If the order is still open or partially filled after matching:
Store order data into
DataStore
Append order to linked list for future matching
If order improves market rates, update lending or borrowing rate accordingly
Code reference:
dataStore.setAddress(...);
OrderQueueLib.appendOrder(...);
if (side == Side.LEND) {
CentuariCLOBDSLib.setMarketLendingRate(...);
}
4️⃣ Order Execution: _matchOrder
When a match is found:
Update both orders’ remaining amounts and statuses
Adjust collateral proportionally
Call Centuari protocol core functions:
supply
— adds matched loan amountsupplyCollateral
— registers collateralborrow
— records borrowing position
Transfer loanToken between trader addresses via Centuari
If fully filled, unlink order from linked list
Emit
OrderMatched
event
Code reference:
CENTUARI.supply(...);
CENTUARI.supplyCollateral(...);
CENTUARI.borrow(...);
CENTUARI.transferFrom(...);
5️⃣ Order Cancellation: cancelOrder
Allows a trader to cancel their open order:
Verifies market is still active
Confirms ownership of the order
Resets all order data in
DataStore
Removes order from linked list queue
Returns assets (loanToken or collateralToken)
Emits
OrderCancelled
event
Code reference:
CENTUARI.transferFrom(config, config.loanToken, address(this), msg.sender, amount);
📌 Market Management
DataStore Creation via
createDataStore
— each market gets its own contract for data isolation.Market Active State Check via
onlyActiveMarket
modifier ensures no new orders on expired markets.
📌 Summary
Centuari’s CLOB module implements a gas-efficient, decentralized matchmaking system with:
Per-market isolated DataStores
Fair price-time priority matching
Partial fill handling
Real-time interest rate updates
On-chain collateral management
Event-driven state change notifications
It provides fine-grained market control and liquidity matchmaking natively on-chain, without external dependencies.
Last updated