Skip to main content
Coming Soon: The Developers section is under active development. Documentation will be available soon.

Overview

The OrderBook contract handles on-chain settlement for Centuari’s fixed-rate lending protocol.
Hybrid Architecture Note: Centuari uses a hybrid orderbook model. Order storage and matching happen off-chain for speed and zero gas costs. The on-chain contract handles settlement, position management, and CBT token operations.

Contract Address

NetworkAddress
Arbitrum One0x...
Arbitrum Sepolia0x...

Functions

placeLendOrder

Create a new lending order.
function placeLendOrder(
    address asset,
    uint256 amount,
    uint256 rate,
    uint256 maturity
) external returns (bytes32 orderId)
Parameters:
NameTypeDescription
assetaddressToken to lend (USDC, etc.)
amountuint256Amount to lend (in token decimals)
rateuint256Fixed rate in basis points (800 = 8%)
maturityuint256Maturity timestamp
Returns: Order ID (bytes32) Example:
// Lend 10,000 USDC at 8% for 90 days
bytes32 orderId = orderBook.placeLendOrder(
    USDC_ADDRESS,
    10000 * 1e6,  // 10,000 USDC
    800,          // 8% APY
    block.timestamp + 90 days
);

placeBorrowOrder

Create a new borrowing order.
function placeBorrowOrder(
    address asset,
    uint256 amount,
    uint256 maxRate,
    uint256 maturity
) external returns (bytes32 orderId)
Parameters:
NameTypeDescription
assetaddressToken to borrow
amountuint256Amount to borrow
maxRateuint256Maximum acceptable rate (basis points)
maturityuint256Maturity timestamp
Requirements:
  • Caller must have sufficient collateral deposited
  • Health factor must remain > 1 after borrow

cancelOrder

Cancel an unfilled or partially filled order.
function cancelOrder(bytes32 orderId) external
Parameters:
NameTypeDescription
orderIdbytes32ID of order to cancel
Requirements:
  • Caller must be order maker
  • Order must not be fully filled

matchOrders

Execute matching between lend and borrow orders.
function matchOrders(
    bytes32 lendOrderId,
    bytes32 borrowOrderId
) external
Note: Typically called by keeper bots, but permissionless.

View Functions

getOrder

function getOrder(bytes32 orderId) external view returns (Order memory)

getOrderBook

function getOrderBook(
    address asset,
    uint256 maturity
) external view returns (
    Order[] memory lends,
    Order[] memory borrows
)

getBestRates

function getBestRates(
    address asset,
    uint256 maturity
) external view returns (
    uint256 bestLendRate,
    uint256 bestBorrowRate
)

Data Structures

Order

struct Order {
    address maker;          // Order creator
    address asset;          // Token address
    uint256 amount;         // Original amount
    uint256 filledAmount;   // Amount already matched
    uint256 rate;           // Rate in basis points
    uint256 maturity;       // Maturity timestamp
    bool isLend;            // true = lend, false = borrow
    OrderStatus status;     // Current status
    uint256 createdAt;      // Creation timestamp
}

enum OrderStatus {
    Open,
    PartiallyFilled,
    Filled,
    Cancelled
}

Events

event OrderPlaced(
    bytes32 indexed orderId,
    address indexed maker,
    address asset,
    uint256 amount,
    uint256 rate,
    uint256 maturity,
    bool isLend
);

event OrderMatched(
    bytes32 indexed lendOrderId,
    bytes32 indexed borrowOrderId,
    uint256 matchedAmount,
    uint256 rate,
    address cbtAddress
);

event OrderCancelled(
    bytes32 indexed orderId,
    uint256 unfilledAmount
);

event OrderExpired(
    bytes32 indexed orderId
);

Error Codes

error InsufficientBalance();
error InsufficientCollateral();
error OrderNotFound();
error OrderNotCancellable();
error InvalidRate();
error InvalidMaturity();
error MatchingFailed();

Integration Example

import { ethers } from 'ethers';

const orderBook = new ethers.Contract(
    ORDER_BOOK_ADDRESS,
    ORDER_BOOK_ABI,
    signer
);

// Place lend order
const tx = await orderBook.placeLendOrder(
    USDC_ADDRESS,
    ethers.parseUnits('10000', 6),
    800, // 8%
    Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60
);

const receipt = await tx.wait();
const event = receipt.events.find(e => e.event === 'OrderPlaced');
const orderId = event.args.orderId;

console.log(`Order placed: ${orderId}`);