Assetera Docs
Smart contracts

Offer lifecycle

The regulator-mandated targeted offer and counter-offer negotiation flow in AsseteraExchange.

An offer is a bilateral, targeted negotiation: a maker proposes specific terms to a specific taker, who may accept, counter, or walk away. Unlike an order (open to any taker), an offer is aimed at one counterparty and supports back-and-forth counter-proposals before either side commits funds.

This targeted offer / counter-offer flow is a regulatory requirement, not an optional convenience. As a MiFID venue, Assetera must support directed, negotiable quotes between a named maker and a named taker. It is a first-class part of the exchange, not sugar over the order book.

State machine

The on-chain OfferStatus enum is: None, Open, Countered, Accepted, Settled, Cancelled, ForceCancelled, Expired. Each offer tracks proposedBy, the party whose terms are currently on the table, and whose tokens are escrowed for the current round.

Making an offer

makeOffer(taker, makerToken, makerAmount, takerToken, takerAmount, expireTs, att) opens an offer targeted at taker, requiring a KYC attestation for the MakeOffer action. It snapshots the fee terms onto the offer (fixed at makeOffer, never renegotiated) and emits OfferMade. The maker cannot target themselves. It returns the new offer id.

Countering

replaceOffer(offerId, newMakerAmount, newTakerAmount, expireTs, att) is the negotiation step: either party (maker or taker) can put fresh terms on the table while the offer is Open or Countered, requiring a KYC attestation for the ReplaceOffer action. It flips proposedBy to the caller (the new proposer's side becomes the escrowed side) and emits OfferReplaced. Fee terms do not change across counters; they stay fixed from makeOffer. Counters can go back and forth any number of times.

Accepting

acceptOffer(offerId, att) is called by the non-proposing party (you can't accept your own proposal), requiring a KYC attestation for the AcceptOffer action. It escrows the accepting side's tokens (so at this point both sides are escrowed), moves the offer to Accepted, and emits OfferAccepted with the agreed terms.

Settling

settleOffer(offerId, makerAtt, takerAtt) is an operator action (OPERATOR_ROLE) that finalizes an accepted offer, swapping the escrowed tokens between the two parties and moving the offer to Settled. It requires a fresh KYC attestation from both parties for the SettleOffer action. It emits OfferSettled; note the received amounts in that event are already net of fee.

Roadmap: as with order settlement, on-chain operator settlement is being parked for the production baseline. settleOffer is present on the current testnet contract but is not part of the intended production standard flow.

Cancelling and expiry

Either party can cancel while the offer is Open or Countered via cancelOffer(offerId, att) (KYC-gated on the CancelOffer action), which returns the currently-escrowed proposer's side and emits OfferCancelled. Offers past their expireTs are swept by the permissionless, batched sweepExpiredOffers(ids[]), which returns escrow to the current proposedBy and emits one OfferExpired per swept id.

The admin escape hatch cancelOfferForUser(offerId, makerRecipient, takerRecipient) works in any non-terminal state (including Accepted, where both legs are escrowed) and emits OfferForceCancelled.

The CancelOffer and SettleOffer actions are deliberately distinct from the order-side Cancel and Settle actions: an attestation signed for one can never be replayed against the other.

For the full event field lists, see Events. For how attestations are produced, see Attestations.

On this page