Table of Contents

Class OnchainReceiveGates

Namespace
NArk.ArkadeIntents.Onchain
Assembly
NArk.ArkadeIntents.dll

The checks run immediately before an on-board funds its L1 HTLC — never at quote time.

public static class OnchainReceiveGates
Inheritance
OnchainReceiveGates
Inherited Members

Remarks

The same shape of danger as OnchainSendGates and the opposite arrangement of it. There the client funded Arkade and its own refund had to open last; here the client funds L1 and the solver's Arkade refund must open first, because the solver is the one paying out ahead of being paid.

The numbers are bound to the send leg's rather than copied, because they measure the same physical facts — a block interval, and the time it takes to get a spend confirmed. Two constants that must agree and are written twice are two constants that will eventually disagree, and the symptom is a corridor that funds swaps its own mirror image refuses.

Fields

AbandonedGraceSeconds

How long past the L1 refund locktime an HTLC that never saw a payment stays watched.

public const long AbandonedGraceSeconds = 86400

Field Value

long

ClaimMarginSeconds

Time that must remain on the L1 leg after the funding has confirmed.

public const long ClaimMarginSeconds = 5400

Field Value

long

Remarks

On this leg it is the solver's claim that has to fit inside it. That is still our problem: a solver that cannot safely claim will not fund the Arkade side at all, so a quote leaving it no room is one whose L1 funding would sit there until we refunded it.

MaxMinConfirmations

The most confirmations this corridor will wait for. MaxMinConfirmations.

public const int MaxMinConfirmations = 6

Field Value

int

MinHeadroomSeconds

Minimum time before our Arkade claim window closes. MinHeadroomSeconds.

public const long MinHeadroomSeconds = 5400

Field Value

long

OrderMarginSeconds

How far the solver's Arkade refund must open before our L1 one.

public const long OrderMarginSeconds = 900

Field Value

long

Remarks

The reference solver sizes its own Arkade refund as htlc_locktime minus exactly this, capped, so a well-formed quote satisfies this by construction and nothing legitimate is refused by checking it. What it catches is a quote that is not well formed: the ordering is the corridor's central safety property and neither contract enforces it, so a client that does not check it is trusting the counterparty for the one thing the design says not to.

Which way round matters. The solver claims L1 with the preimage our Arkade claim published, so its Arkade lockup must become reclaimable before our L1 refund does — otherwise there is a window in which we can take the L1 sats back while still holding a claimable Arkade lockup, and one leg pays for both. Refusing here is refusing to be handed that window: a swap we could only complete by robbing the counterparty is one no honest solver offered.

SecondsPerBlock

Nominal seconds per block. SecondsPerBlock.

public const long SecondsPerBlock = 600

Field Value

long

Methods

AssertAmounts(RfqQuote<OnchainReceiveQuoteProfile>, long, RfqAmountSide)

Hold a quote to the amount that was asked for, on the leg the request pinned.

public static void AssertAmounts(RfqQuote<OnchainReceiveQuoteProfile> quote, long requestedSats, RfqAmountSide amountSide)

Parameters

quote RfqQuote<OnchainReceiveQuoteProfile>

The solver's quote.

requestedSats long

The amount the request named.

amountSide RfqAmountSide

Which leg that amount pinned.

Remarks

Exact-in is checked both ways: the payer's figure is one a third party has been quoted, so a charge under it under-credits the swap as surely as one over it overcharges. Exact-out only bounds the payout from below, since a fee correction may deliver a satoshi more.

Exceptions

OnchainReceiveNotFundableException

The quote prices a different trade.

AssertFundable(RfqQuote<OnchainReceiveQuoteProfile>, long)

Refuse a quote this corridor cannot safely fund.

public static void AssertFundable(RfqQuote<OnchainReceiveQuoteProfile> quote, long now)

Parameters

quote RfqQuote<OnchainReceiveQuoteProfile>

The solver's quote.

now long

The current time, unix seconds.

Exceptions

OnchainReceiveNotFundableException

Any check refused.

AssertPayoutAboveDust(RfqQuote<OnchainReceiveQuoteProfile>, long)

Refuse a quote whose payout could not become a VTXO.

public static void AssertPayoutAboveDust(RfqQuote<OnchainReceiveQuoteProfile> quote, long dustSats)

Parameters

quote RfqQuote<OnchainReceiveQuoteProfile>

The solver's quote.

dustSats long

The Arkade server's dust limit, in sats.

Remarks

Matters on exact-in, where the fee comes out of the payout: a small order can leave a lockup the claim cannot spend into an output, and the payer's L1 funding then waits out the HTLC locktime.

Exceptions

OnchainReceiveNotFundableException

The payout is below dustSats.

ClaimWindowIsOpen(long, long)

Whether there is still time to claim the Arkade lockup before the solver's reclaim opens.

public static bool ClaimWindowIsOpen(long arkadeRefundLocktime, long now)

Parameters

arkadeRefundLocktime long

The quote's refund_locktime, unix seconds.

now long

Unix seconds.

Returns

bool

true while claiming is still safe.

Remarks

The mirror of ClaimWindowIsOpen(long, long), on the rail the roles put it. Claiming into a closing window is a race we can lose after showing our hand: the claim publishes the preimage, so losing it hands the solver both legs.

RefundIsDue(long, long)

Whether the L1 HTLC's refund leaf has matured.

public static bool RefundIsDue(long htlcLocktime, long medianTimePast)

Parameters

htlcLocktime long

The leaf's absolute locktime, unix seconds.

medianTimePast long

The chain tip's median time past (BIP-113) — not wall clock.

Returns

bool

true once a refund spend would be accepted.

Remarks

Consensus matures CLTV against median time past, which trails wall clock by around an hour. Comparing against a local clock therefore produces a transaction that looks due and is rejected as non-final, and the rejection arrives with no indication that the deadline was simply read off the wrong clock.