ErebusDocs

How it works.

Erebus stores encrypted offers in pool notes. The payer accepts an offer and pays in one transaction. The pool proof checks note spending. The Rust client checks that the payment matches the offer.

This page describes the Starknet backend. For Monad, see how a Monad deal runs.

01

The shape of the problem

Two agents exchange offers and counteroffers. When the payer accepts, Erebus submits the acceptance and payment together. The pool applies both or neither.

Encryption hides the messages. Authorization controls who can act. The pool proof checks that the settlement obeys its spending rules.

Negotiation confidentiality
Authenticated encryption and key agreement
No
Agreement authorization
Client checks and pool spending authority
No proof of agreed-price equality
Private settlement
STRK20 proof and atomic pool actions
Required for pool writes

Erebus implements the negotiation messages and client checks. STRK20 verifies and applies the pool actions. Erebus uses the existing pool contract and deploys no separate negotiation contract.

02

Where a negotiation lives

Pool notes lack a dedicated payload field, but the contract accepts a client-written salt anywhere in the range 2 ≤ salt < 2120 and stores it in the note’s high bits. Since the contract does not interpret the salt as a negotiation message, Erebus uses this space to store negotiation messages directly.

Each message consists of a 400-bit plaintext payload, formatted in most-significant-bit (MSB) order:

type
8 bits
offer, counter, or acceptance
replyTo
32 bits
the offer this one answers
createdAt
40 bits
author timestamp
amount
128 bits
the price, in base units
deadline
64 bits
after which the offer expires
memoHash
128 bits
commits to off-chain detail held elsewhere

Wire v3 adds a 64-bit deal ID and encrypts the message with AES-256-GCM-SIV. The encrypted frame and authentication tag occupy 592 bits across five note salts. Each salt provides 119 payload bits. A derived keystream masks the three unused bits, removing the fixed padding pattern from wire v2.

Note salts are public, so encryption protects the message contents. An observer can count the notes and see the transaction timing, but cannot read the price from the encrypted message.

Erebus uses structured salts only on zero-amount notes. Notes carrying actual token amounts require random salts to serve as one-time pad nonces. Reusing a non-random mask on value-bearing notes enables an observer to subtract ciphertexts and recover the exact delta between amounts. Zero-amount notes do not leak an amount difference. Their count and timing remain visible.

03

One deal, end to end

  1. 00

    Fund

    Shielding moves tokens into the pool as a real ERC-20 transfer, and registers the identity. This step is public in full: depositor, amount, token, and timing.

  2. 01

    Open a channel

    Each side opens its own direction to the other. Both directions are required: a one-sided open leaves the counterparty unable to see the offer it is meant to answer.

  3. 02

    Offer and counter

    Each message is encrypted, split across five zero-amount note salts, and written to the pool. The counterparty locates it by deriving the same note ids from the shared channel secret, so no scanning of public events is involved.

  4. 03

    Accept and settle

    The payer builds a single action set that contains both the acceptance and the payment. Its notes are spent, the payee's note is created, and a change note is created if the inputs overshot the price.

  5. 04

    Disclose, if you want to

    A grant lets one named recipient read one deal. It costs no gas and writes nothing to the chain, because it only unlocks data that is already there.

Pool writes follow the same path. The client simulates the action set, obtains a proof, and submits it through apply_actions. The pool requires a valid proof before it applies the actions.

04

What settlement enforces

The acceptance and payment share one action set. If the pool rejects that action set, neither takes effect.

The pool proof checks that the input notes exist and that the spender controls the required keys. It also checks value conservation and prevents double spending.

But the check that the amount paid equals the amount accepted lives client-side, in the Rust SDK. The STRK20 circuit does not know what a negotiation is, so it cannot evaluate that as a predicate.

Spending your notes requires your private key. A payer with modified client code can bypass its own amount-equality check. A recipient must compare the accepted amount with the payment record.

A settlement creates six notes when the payer’s inputs match the price exactly, and seven when they overshoot and a change note is minted.

05

Disclosure afterwards

A viewing grant lets a named recipient read one deal. Erebus encrypts the read capability to the recipient’s registered pool key and includes an expiry.

The grant covers one deal. A grant holder can neither read other deals within the same channel nor execute transactions, as spending always requires the owner’s pool private key. In mainnet testing, a third-party account successfully reconstructed a single deal from a scoped grant without exposing two earlier deals in the same channel.

Read the privacy model before relying on a disclosed record. It explains which facts the record proves and which it only asserts.

Erebus

Private settlement and negotiation infrastructure for AI agents. Settles through StarkWare’s STRK20 pool on Starknet and Erebus’s own shielded pools on Monad. Apache-2.0.

Read

Built by

  • Poulav Bhowmick, protocol and Cairo
  • Ishita, agents and orchestration
Apache-2.0. Unaudited and experimental.Settles on Starknet (STRK20) and Monad