Skip to main content
You interact with the Sundial L2 in four ways. Three happen on L1 and one on L2.

Inclusion times

Every L1 event carries an inclusion_time, fixed when the event is created. It equals the upper bound of the creating transaction’s validity interval plus the event_wait_duration protocol parameter. The wait gives operators time to see the event on L1. Each block claims a time interval, and consecutive intervals cover time with no gaps or overlaps. So an event’s inclusion time falls in exactly one block’s interval. A block that omits an event whose inclusion time lies in its interval, or includes one whose inclusion time lies outside it, is invalid. While operators keep committing valid blocks, every L1 event is included in exactly one block.

Deposit

A deposit is created by an L1 transaction that:
  1. Spends an input that uniquely identifies the deposit.
  2. Registers a witness staking script for it.
  3. Mints a deposit token and sends your funds to the deposit address, with a datum naming the L2 address and optional datum to credit.
When a block includes the deposit, a new L2 UTXO appears at your L2 address holding the deposited value. Once that block is confirmed, the L1 deposit UTXO can be absorbed into the reserve. A deposit can hold at most max_tokens_allowed_in_deposits distinct tokens, ADA included.

Transaction request

The normal way to transact is to submit an L2 transaction to the current operator’s API. See the Transactions API. You set the transaction’s validity interval. The transaction can go into any block whose event interval overlaps it. A valid request misses the ledger only if the operator censors it, or if the last overlapping block was committed before the request arrived.

Transaction order

If an operator ignores your request, post the transaction on L1 as a transaction order. Like a deposit, it carries an inclusion time, and the block covering that time must include it. Operators can’t check an order’s contents when it is created. If the ordered transaction turns out to be invalid, the operator includes it with a tag that says why. A wrong tag makes the block invalid.

Withdrawal order

A withdrawal is created by an L1 transaction that:
  1. Spends an input that uniquely identifies the order.
  2. Registers a witness staking script for it.
  3. Mints a withdrawal order token and sends it to the withdrawal order address, with a datum naming the L2 UTXO to withdraw, its owner and value, the L1 address to pay, and a refund address.
When a block includes the order, the named L2 UTXO is removed from the L2 ledger. After that block is confirmed:
  1. The order moves to a payout accumulator.
  2. The accumulator collects funds from the reserve until it holds the full amount.
  3. The funds are sent to your L1 address.
As with transaction orders, an operator tags an invalid withdrawal order (wrong owner, wrong value, an already-spent UTXO) and a wrong tag makes the block invalid.
A withdrawal can’t be paid before its block is confirmed, and a block is confirmed only after the maturity period. See Protocol parameters.

Witness staking scripts

Each L1 event registers a staking script parametrized by the event’s ID. The registration state of that script proves whether the event exists. This is how a fraud proof shows that an operator fabricated an event: the witness for it was never registered.

The reserve

Absorbed deposits sit in the reserve on L1, one UTXO per deposit. Payout accumulators draw on the reserve to pay confirmed withdrawals and return any excess.

If operators stop

Inclusion times bind operators only while blocks are being committed. If production stops, the escape hatch lets new operators restart it. The first block after an outage has an interval that spans the whole outage, so it must include every event created meanwhile.