# How Akash Implements Bid Matching and Lease Creation in the Market Module

> Learn how Akash implements bid matching and lease creation in its market module. Discover the state-transition workflow that marks winning orders, creates escrows, and stores lease records.

- Repository: [Akash Network/node](https://github.com/akash-network/node)
- Tags: internals
- Published: 2026-02-24

---

**Akash implements bid matching and lease creation through a state-transition workflow in the market module that marks winning orders and bids as active, creates payment escrows, stores lease records, and closes all competing bids as lost.**

The bid matching and lease creation process in the Akash Network is coordinated by the **market module**, which manages the lifecycle of deployment orders, provider bids, and active leases. Located in the `akash-network/node` repository, this module ensures atomic transactions that either complete a lease creation entirely or roll back without side effects. Understanding this flow is essential for developers building on Akash or auditing its decentralized compute marketplace.

## The Lease Creation Orchestration

The entry point for bid matching is the `CreateLease` method in the message handler server. When a user submits a `MsgCreateLease` transaction, the handler validates the entities, establishes payment infrastructure, and executes state transitions.

The high-level flow follows four distinct phases:

1. **Validation** – Load and verify the bid, order, and deployment group are in the correct open state.
2. **Escrow Setup** – Create a payment escrow to lock funds for the lease duration.
3. **State Activation** – Mark the order and winning bid as matched (active).
4. **Cleanup** – Close all competing bids and their escrow accounts.

The implementation in [`x/market/handler/server.go`](https://github.com/akash-network/node/blob/main/x/market/handler/server.go) (lines 78-226) handles this sequence:

```go
func (ms msgServer) CreateLease(goCtx context.Context, msg *types.MsgCreateLease) (*types.MsgCreateLeaseResponse, error) {
    ctx := sdk.UnwrapSDKContext(goCtx)

    // 1️⃣ Load and validate the bid, order and deployment group
    bid,   _ := ms.keepers.Market.GetBid(ctx, msg.BidID)
    order, _ := ms.keepers.Market.GetOrder(ctx, msg.BidID.OrderID())
    group, _ := ms.keepers.Deployment.GetGroup(ctx, order.ID.GroupID())

    // 2️⃣ Create the escrow payment that will hold the lease fee
    err := ms.keepers.Escrow.PaymentCreate(ctx,
        msg.BidID.LeaseID().ToEscrowPaymentID(),
        provider,            // provider address extracted from the bid ID
        bid.Price)           // price agreed in the winning bid
    if err != nil { return nil, err }

    // 3️⃣ Store the lease record
    if err = ms.keepers.Market.CreateLease(ctx, bid); err != nil {
        return nil, err
    }

    // 4️⃣ Mark the order and the winning bid as matched (active)
    ms.keepers.Market.OnOrderMatched(ctx, order)
    ms.keepers.Market.OnBidMatched(ctx, bid)

    // … (losing bids handling – see next section)
    return &types.MsgCreateLeaseResponse{}, nil
}

```

## Matching State Transitions

Once the lease record is created, the system must update the market state to reflect that the order is fulfilled and the specific bid has won.

### Activating the Order

The `OnOrderMatched` function in [`x/market/keeper/keeper.go`](https://github.com/akash-network/node/blob/main/x/market/keeper/keeper.go) (lines 79-84) transitions the order from open to active. This helper reads the current order state, sets `order.State = types.OrderActive`, and delegates storage to `updateOrder`, which uses `collections.IndexedMap` to maintain secondary indexes.

### Activating the Winning Bid

Similarly, `OnBidMatched` (lines 86-90) handles the bid state transition by setting `bid.State = types.BidActive` before calling `updateBid`. Both functions ensure that the underlying `IndexedMap` structures remain consistent, allowing efficient lookups by state and provider.

## Closing Competing Bids

After establishing the winning lease, the system must invalidate all other open bids for the same order. The handler iterates through competing bids using `WithBidsForOrder`, marks each as lost, and closes their escrow accounts.

The cleanup logic in [`x/market/handler/server.go`](https://github.com/akash-network/node/blob/main/x/market/handler/server.go):

```go
// close losing bids
ms.keepers.Market.WithBidsForOrder(ctx, msg.BidID.OrderID(),
    types.BidOpen, func(cbid types.Bid) bool {
        ms.keepers.Market.OnBidLost(ctx, cbid)          // ⇢ set state to BidLost
        // Immediately close the escrow account for the lost bid
        if err = ms.keepers.Escrow.AccountClose(ctx,
            cbid.ID.ToEscrowAccountID()); err != nil {
            return true // stop iteration on error
        }
        return false
})

```

The `OnBidLost` function (lines 93-98 in [`keeper.go`](https://github.com/akash-network/node/blob/main/keeper.go)) sets `bid.State = types.BidLost` using the same `updateBid` helper as the winning path. This ensures that failed bids release their locked funds immediately through `Escrow.AccountClose`.

## Key Implementation Files

Understanding bid matching and lease creation requires familiarity with these core files in the `akash-network/node` repository:

- **[`x/market/keeper/keeper.go`](https://github.com/akash-network/node/blob/main/x/market/keeper/keeper.go)** – Core state-transition helpers including `OnOrderMatched`, `OnBidMatched`, `OnBidLost`, and `CreateLease`.
- **[`x/market/handler/server.go`](https://github.com/akash-network/node/blob/main/x/market/handler/server.go)** – gRPC message server that orchestrates the lease creation transaction flow.
- **`x/market/keeper/keys`** – Key encoding utilities for the `IndexedMap` structures managing order, bid, and lease prefixes.
- **[`upgrades/software/v1.2.0/market.go`](https://github.com/akash-network/node/blob/main/upgrades/software/v1.2.0/market.go)** – Migration logic for transitioning legacy KV-store data to the current `collections.IndexedMap` schema.

## Summary

- **Atomic Execution**: The `CreateLease` handler performs validation, escrow creation, lease storage, and state transitions in a single transaction that rolls back completely on any failure.
- **State Machines**: Orders transition from `Open` to `Active` via `OnOrderMatched`, while winning bids move from `Open` to `Active` via `OnBidMatched` and losing bids move to `BidLost` via `OnBidLost`.
- **Escrow Management**: The system creates a payment escrow for the winning lease via `Escrow.PaymentCreate` while closing escrow accounts for all losing bids via `Escrow.AccountClose`.
- **Data Integrity**: All state changes utilize `collections.IndexedMap` to ensure secondary indexes remain synchronized with primary storage.

## Frequently Asked Questions

### What triggers the bid matching process in Akash?

The bid matching process initiates when a deployment owner submits a `MsgCreateLease` transaction referencing a specific bid ID. This message triggers the `CreateLease` handler in [`x/market/handler/server.go`](https://github.com/akash-network/node/blob/main/x/market/handler/server.go), which validates the bid against the order and executes the matching logic if all conditions are met.

### How does Akash ensure losing bids do not retain locked funds?

After creating the winning lease, the handler iterates through all remaining `BidOpen` states for the order using `WithBidsForOrder`. For each losing bid, it calls `OnBidLost` to update the state and immediately invokes `Escrow.AccountClose` to release the provider's locked collateral, ensuring no funds remain trapped in failed bids.

### What happens if the escrow payment creation fails during lease creation?

If `Escrow.PaymentCreate` returns an error during the `CreateLease` execution, the transaction aborts immediately and returns the error to the caller. Because Cosmos SDK transactions are atomic, any state changes made earlier in the function are discarded, leaving the order and bid in their original `Open` state.

### Where is the lease record actually stored during the matching process?

The lease record is persisted via `ms.keepers.Market.CreateLease(ctx, bid)` within the `CreateLease` handler. This method stores the lease object in the keeper's `IndexedMap` structure, making it queryable by lease ID while maintaining indexes for efficient provider and tenant lookups.