> For the complete documentation index, see [llms.txt](https://docs.zama.org/protocol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zama.org/protocol/confidential-swap/guides/market-makers.md).

# Market makers

Run a market-making agent that prices every candidate in a bundle, quotes blind, and settles the intents it wins.

A market maker runs an off-chain agent that watches new intents, prices every candidate in each bundle, submits encrypted quotes, resolves auctions, and settles the ones it wins.

The only hard dependencies are the protocol contract, an EVM client, and the Zama SDK. Your RPC host, event source, pricing strategy and persistence are your own choices.

## What you can and cannot see

| Field                               | Visible to you             |
| ----------------------------------- | -------------------------- |
| Each candidate's pair and direction | yes, plaintext             |
| Each candidate's `eAmountIn`        | yes, via delegated decrypt |
| Which candidate is real             | **no** — until you win     |
| The maker's slippage floor          | **no**, ever               |
| Other market makers' quotes         | **no**                     |
| The winner, after resolution        | yes, publicly decryptable  |

You quote blind to the floor, blind to your competitors, and blind to which order you are actually competing for. To win you must submit the highest quote on the real order, and that quote must be at or above the maker's hidden floor.

## Prerequisites

1. **A funded EOA.** It signs decryption permits and your transactions. One agent, one identity.
2. **`MARKET_MAKER_ROLE`**, granted by a protocol admin.
3. **Confidential balances initialized on every asset** of every pair you quote — not just the ones you expect to trade.
4. **Operator authority** for the swap contract on those assets, so it can pull your output at settlement.

{% hint style="warning" %}
**Initialize every leg, not just the ones you trade.** Settlement transfers on every asset the bundle touches, and whether your balance on an asset exists is public — so settling with one of them uninitialized would single out the real order. The contract rejects the settlement rather than leaking it, with `ConfidentialSwap__ConfidentialBalanceNotInitialized`.
{% endhint %}

{% hint style="info" %}
**You can only see intents created after you were granted the role.** Granting or revoking the role redeploys the protocol's decryption context, and each intent snapshots the context that existed when it was created. Intents older than your grant are permanently undecryptable to you.
{% endhint %}

Check all four at startup, for every pair you intend to quote, and skip any pair that fails. Winning an auction you cannot settle earns you nothing, and the maker gets nothing back until the settlement window expires and the intent is reclaimed.

## The loop

```
maker          --> createIntent        (bundle of 2-6 candidates, one real)
  |   -- QUOTING --
you            --> quoteIntent          (one quote per candidate)
anyone         --> resolveQuoting       (after the window, or once everyone has quoted)
  |   -- SETTLEMENT --
winning maker  --> settleIntent
anyone         --> reclaimExpiredIntent (if unfilled)
```

### 1. Decrypt the candidates

Rights reach you through the per-intent delegation context carried on `IntentCreated`. Use the one from the event — never a cached context from another intent.

```ts
const mmAccess = intent.marketMakerDecryptionAccess;
const clear = await sdk.decryption.delegatedDecryptValues(
  intent.orders.map((o) => ({ encryptedValue: o.eAmountIn, contractAddress: mmAccess })),
  SWAP_CONTRACT_ADDRESS, // the delegator
);
```

You cannot decrypt the real index or the floor.

### 2. Price every candidate

You do not know which order is real, so **every quote must be one you are willing to honour**. A deliberately bad quote on a candidate you assume is a decoy is a quote you will be held to if you guessed wrong.

### 3. Submit your quotes

One quote per order, in the bundle's order. A mismatched count is rejected.

```ts
const { encryptedValues, inputProof } = await sdk.encrypt({
  contractAddress: SWAP_CONTRACT_ADDRESS,
  userAddress: me,
  values: quotes.map((q) => ({ value: q, type: "euint64" as const })),
});

await walletClient.writeContract({
  address: SWAP_CONTRACT_ADDRESS, abi, functionName: "quoteIntent",
  args: [intentId, encryptedValues, inputProof],
});
```

The fee is skimmed from your quote on its way to the maker, so your outlay is exactly what you quoted.

You may quote repeatedly — the contract keeps your running maximum, so a lower re-quote cannot undercut your own standing. **Quotes cannot be cancelled.** Quoting stays open until the window elapses or the intent is resolved, whichever comes first.

### 4. Resolve

Permissionless, and it reverts if already done. Simulate first, or read the intent, rather than racing.

```ts
await walletClient.writeContract({
  address: SWAP_CONTRACT_ADDRESS, abi, functionName: "resolveQuoting", args: [intentId],
});
```

Resolution can run early — before the quoting window ends — once every market maker snapshotted at the intent's creation has submitted a first quote.

### 5. Detect a win, and learn what you won

The winner is publicly decryptable after resolution:

```ts
const { clearValues } = await sdk.decryption.decryptPublicValues([eBestQuoter]);
const won = (clearValues[eBestQuoter] as string).toLowerCase() === me.toLowerCase();
```

If you won, `IntentResolved` tells you which candidate was real — but only to you. It carries `eMaskedIndex`, publicly decryptable and a uniformly random byte to everyone else; XOR it with your own mask and you get the real order's index.

Your mask is a one-time pad generated for you at your first quote on that intent. Read it from `eIndexMask` on your own `IntentQuoted` event, or from `getIndexMask(intentId, you)` — the handle is public either way, and only you can decrypt it:

```ts
const mask = await publicClient.readContract({
  address: SWAP_CONTRACT_ADDRESS, abi, functionName: "getIndexMask", args: [intentId, me],
});
const clear = await sdk.decryption.decryptValues([{ encryptedValue: mask, contractAddress: SWAP_CONTRACT_ADDRESS }]);
const realIndex = Number(clear[mask]) ^ Number(maskedIndex);
```

To everyone else that published value is a uniformly random byte.

### 6. Settle the intent

Now that you know which order you filled, check that your confidential balance on its output asset covers the amount you quoted, then settle. The contract requires the public-decryption proof of `eBestQuoter` — the one you obtained when you decrypted the winner — so only the winner can settle:

```ts
const { decryptionProof } = await sdk.decryption.decryptPublicValues([eBestQuoter]);
await walletClient.writeContract({
  address: SWAP_CONTRACT_ADDRESS, abi, functionName: "settleIntent", args: [intentId, decryptionProof],
});
```

The call reverts if you do not hold `MARKET_MAKER_ROLE`, if you are not delegated on this intent, if the proof does not attest your address, or if `settlementEndsAtBlock` has passed.

If your balance does not cover the amount, the transaction still succeeds but settles nothing: the transfers move zero, `eSucceed` stays false, and the intent is not finalized. Fund the asset and call again while the window is still open. Confirm the settlement by public-decrypting `eSucceed` on `IntentSettled`, never by the absence of a revert.

Funding mid-window can leak information. Wrapping more liquidity is a public transaction, and doing it just before you settle tells observers something about the trade you are settling. Keep your inventory pre-funded instead — see [Protecting your privacy](/protocol/confidential-swap/protocol/privacy.md) to learn more.

## Running in production

* **One wallet per agent, for the whole lifecycle.** The role, the delegation, your index mask and the right to settle are all bound to the address that quoted. Another address cannot pick up an intent you quoted, so the wallet has to stay available from quoting through settlement.
* **Keep every asset you quote initialized and stocked in advance.** Funding once you have already won leaves you racing the settlement window. It is also visible: any activity on your wallet — a wrap, an unwrap, a transfer — is public and can be lined up against the intents you settled, exposing trades that were confidential when they happened. Those are your counterparties' trades, not only your own, so the privacy makers get is partly your responsibility.
* **Keep your quoting deliberate.** Re-quoting is allowed and only your highest quote stands, but every extra quote adds to the decryption work the winner has to fit inside the settlement window.

## Next steps

* [Decoy bundles](/protocol/confidential-swap/protocol/decoy-bundles.md) — what you are actually quoting against
* [Events and errors](/protocol/confidential-swap/reference/events-and-errors.md) — the reverts worth handling
* [Contract interface](/protocol/confidential-swap/reference/contract-interface.md) — every entry point with its gate


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.zama.org/protocol/confidential-swap/guides/market-makers.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
