
Every coin on Stag Hunt lives inside an on-chain Kaspa covenant— a tiny program compiled into the very UTXO that holds your KAS. It can do exactly two things: pay the winner when a hunt is delivered, or refund you when it isn't. No admin key. No custodial wallet. No third path.
The platform holds no keys that can move funds. Your coins sit in a P2SH covenant address the moment you contribute — governed only by the script.
The refund branch needs no signature and no server. If every referee — and Stag Hunt itself — vanished tomorrow, you could still reclaim your funds after the deadline.
The payout branch can only pay the verified winner. There is no fee output the script will accept, so no cut can be skimmed on-chain.
Every hunt exposes its compiled redeem script, quorum, and refund DAA. You can verify the exact rules before committing a single coin.
When you back a hunt, Stag Hunt compiles a redeem script just for you and hands you its P2SH address. Your KAS pays straight into it.
From this moment the coins can only move the way the script allows. Baked in: your refund address, and the frozen M-of-N referee committee.
The winner is paid by an M-of-N Schnorr multisig of the hunt's frozen referee pubkeys. The threshold is a simple majority — M = floor(N / 2) + 1 — so a 5-referee hunt needs 3 signatures, a 3-referee hunt needs 2.
Referees sign partial signatures off-chain. Once M of them exist, anyone can assemble and broadcast the release transaction — the referees never need to be online at the same moment, and no coordinator holds the funds.
Guarded by OP_CHECKLOCKTIMEVERIFY against a fixed Kaspa DAA score (the deadline). Before the deadline this path is dead; after it, it opens to everyone.
The script then pins the output: the refund transaction must have exactly one output, and that output's script must equal the address you committed at fund time. So even though anyone may broadcast it, the coins can only ever land in your wallet.
This is the actual covenant compiled for every contribution — an OP_IF / OP_ELSE switch. The spender pushes a boolean to pick a branch. Nothing else can move the coins.
OP_IF ; ── PAYOUT: refs co-sign a release ── OP_<M> <pk₁> <pk₂> … <pk_N> OP_<N> OP_CHECKMULTISIG OP_ELSE ; ── REFUND: permissionless after deadline ── <T_hunt_end_daa> OP_CHECKLOCKTIMEVERIFY OP_TXOUTPUTCOUNT OP_1 OP_EQUALVERIFY ; exactly one output OP_0 OP_TXOUTPUTSPK <backer_spk> OP_EQUAL ; …paying only you OP_ENDIF
OP_CHECKMULTISIGVerifies M valid Schnorr signatures against the N frozen referee pubkeys. Pubkeys are sorted KIP-39-canonically so signatures line up with the redeem's iteration order.
OP_CHECKLOCKTIMEVERIFYBlocks the refund until the chain's DAA score passes the deadline. Kaspa's CLTV consumes the locktime operand — no trailing OP_DROP, unlike Bitcoin.
OP_TXOUTPUTCOUNT · OP_1Forces the refund transaction to carry a single output, so no sneaky extra output can siphon change elsewhere.
OP_TXOUTPUTSPK · OP_EQUALIntrospects the spending transaction and asserts output 0 pays the exact script pubkey you committed. This is what binds the refund to your address.
The address you pay into is a Pay-to-Script-Hash (P2SH, Kaspa address version 8). It is a pure function of the redeem script — so the same committee, quorum, deadline, and refund address always produce the same address, and anyone can recompute it to check nothing was swapped.
; 1. compile the redeem script (see above) → raw bytes redeem = OP_IF … OP_ENDIF ; ≤ 520 bytes ; 2. BLAKE2b-256 the redeem bytes (unkeyed, 32-byte digest) h = blake2b_256(redeem) ; 3. build the script-hash SPK (version 8, big-endian) spk = 0x00 0x08 ‖ OP_BLAKE2B OP_DATA_32 h OP_EQUAL ; 4. bech32-encode (prefix + version 8) → the funding address addr = bech32("kaspa", h, version=8)
DeterministicNo randomness, no server secret. Feed the same parameters in, get the same kaspa:… address out — on any machine, in any language.
Commit-then-revealThe chain only ever sees the 32-byte hash until you spend. The full redeem script is revealed in the spending transaction, where nodes re-hash it and check it matches — so the rules can't be altered after funding.
To spend a P2SH output you provide a signatureScript that (a) satisfies one branch and (b) ends by pushing the full redeem script. Nodes hash that trailing push, confirm it matches the address, then execute it against the rest of the stack. The two branches build completely different witnesses.
; PAYOUT — M framed Schnorr sigs, then TRUE selector OP_DATA_65 <sig₁‖0x01> OP_DATA_65 <sig₂‖0x01> ; …M of them OP_1 ; picks the OP_IF branch push <redeem>
; REFUND — no signature at all OP_0 ; picks the OP_ELSE branch (FALSE) push <redeem> ; plus, on the transaction itself: input.sequence = 0 ; un-finalize so CLTV applies tx.lockTime = <T_hunt_end_daa>
Why sequence = 0Kaspa's OP_CHECKLOCKTIMEVERIFY is a no-op on a finalizedinput (max sequence). Setting the input sequence to 0 "un-finalizes" it so the locktime is actually enforced — this is what makes the refund impossible to broadcast one block early.
A normal timelock would let anyone spend the coins to anywhereonce it expires. Stag Hunt's refund branch closes that hole using Kaspa's introspection opcodes, which let a script read the spending transaction's own outputs and assert facts about them:
OP_TXOUTPUTCOUNT OP_1 OP_EQUALVERIFY ; the tx must have EXACTLY one output OP_0 OP_TXOUTPUTSPK <backer_spk> OP_EQUAL ; output[0]'s script MUST equal your address
OP_TXOUTPUTSPK pushes the full serialized script-public-key of output 0 — the version (big-endian u16) ‖ script— and the script compares it byte-for-byte against the SPK of the refund address you committed at funding time. Combined with the "exactly one output" check, the outcome is fixed: the onlytransaction the refund branch will ever accept is one that sends the whole UTXO (minus fee) to you. It's permissionless to broadcast but impossible to redirect.
Referee keys are 32-byte x-only Schnorr public keys. The payout branch is a bare OP_CHECKMULTISIG over the N committee keys with threshold M = ⌊N/2⌋ + 1. Each referee signs the transaction sighash independently and off-chain; once M partial signatures exist, anyone can assemble and broadcast — no coordinator ever holds funds or keys.
OP_CHECKMULTISIGwalks the redeem's pubkeys and the witness's signatures in lockstep — it does not try every combination. So both the committed keys and the collected signatures are sorted lexicographically ascendingby pubkey. Signers that don't sort identically would trip a NullFail and the whole spend would be rejected.
SighashKaspa signs a BLAKE2b keyed hash committing to the inputs, outputs, and amounts (SIGHASH_ALL, byte 0x01 appended to each 64-byte signature). Change any output and every signature is invalidated — which is exactly why the collected referee signatures also lock in who gets paid.
The deadline is a DAA score— Kaspa's difficulty-adjusted block count, a monotonic on-chain clock that can't be gamed by timestamp fiddling. The refund branch opens the instant the chain's DAA score passes the committed value.
8-byte LE u64The locktime operand is pushed as a fixed 8-byte little-endian integer — notBitcoin's CScriptNum. It commits the exact DAA score into the script bytes (and therefore into the address).
CLTV popsUnlike Bitcoin, Kaspa's OP_CHECKLOCKTIMEVERIFY consumes its operand from the stack. Adding a trailing OP_DROPwould underflow the stack — so Stag Hunt's script deliberately omits it.
Grace windowThe refund DAA is set a few days after claims close, giving referees a window to sign a legitimate payout before backers can start reclaiming.
Both spend transactions are single-input, single-output. Their fee is sized as feerate × mass, computed from the finalized transaction the same way at every signer and broadcaster so the referee signatures always cover the exact fee that ships.
Mass-derived feeOn mainnet the network floor is ~100 sompi/gram; a covenant spend is a few thousand grams of mass (the redeem script rides inside the witness), so the real fee is a fraction of a KAS.
KIP-9 dust floorA refund/release output below ~0.2 KAS is non-standard and the network rejects it — which is why contributions have a 1 KAS practical minimum. Below the floor, the covenant UTXO could never be spent back out.
When you spend, the whole redeem script is pushed as a single data element in the witness — and Kaspa caps a script data element at 520 bytes (MAX_SCRIPT_ELEMENT_SIZE). That cap, not the multisig's 20-key limit, is what bounds the committee.
fixed overhead (IF/ELSE, CLTV, introspection, 35-byte backer SPK) ≈ 58 bytes per referee (OP_DATA_32 + 32-byte pubkey) = 33 bytes N = 13 → 58 + 33·13 = 487 bytes ; ✓ 33 to spare N = 14 → 58 + 33·14 = 520 bytes ; exactly at the cap
Stag Hunt ships at N ≤ 13 for safety headroom. Committees run from 1-of-1 (testing) up to 7-of-13, always at simple majority.
No. The platform holds no key that satisfies either branch and never appears in the script. It can't sign a payout or a refund.
No. The payout branch has no output constraint, but the referees only ever sign a transaction paying the verified winner — and it takes a majority colluding to sign anything at all. They can't pay themselves without M of them agreeing on-chain, in public.
No. The refund branch is pinned by introspection to a single output equal to your committed address. A different output fails OP_EQUAL and the transaction is invalid.
You still get refunded. After the deadline DAA, the refund branch needs no signature — anyone can broadcast it, and it can only pay you.
No. The rules ARE the address. Any change to the committee, quorum, deadline, or your refund address produces a different address that your coins were never sent to.
No. The committee is frozen into every backer's script at funding time. New referees would only affect hunts funded after the change.
M = floor(N / 2) + 1OP_CHECKLOCKTIMEVERIFY on a Kaspa DAA score (8-byte LE u64)520-byte element limit (grows ~33 bytes per referee)Because reviewable code holds the money instead of a company, the safety of your funds rests on math you can audit rather than a promise. On any hunt, open View the on-chain covenant to inspect the committed referee committee, the exact quorum, and the refund DAA — before you contribute a single coin.
Browse hunts →