Opening soon. Chests are not on sale yet. Sign up now so your account is ready the moment they go live.

How fairness works

Before a chest goes live we lock in what is inside and the order it sits in, and we publish a fingerprint of that lock. After the chest is done we hand over the key so anyone can check it.

The plain-English version

  1. We pick the products. A limited chest is a fixed list of real, vaulted items. We write the list of item ids down, sorted, and hash it. That hash is the manifestHash. It proves the set of items cannot change after publish.
  2. We draw a secret seed. 32 random bytes. We publish only its hash, the seedHash. The seed itself stays secret while the chest is selling.
  3. We publish a commitment. One more hash that ties the fairness version, the seed hash and the manifest hash together. This is the fingerprint shown on the chest page and in the table below.
  4. The seed shuffles the items. A standard Fisher-Yates shuffle driven by a keystream derived from the seed places each item in a numbered slot. Same seed and same manifest always give the same order, so anyone can reproduce it later.
  5. Each purchase takes one slot. Your browser sends a random clientSeed with the order. We hash the secret seed, the purchase number (nonce) and your clientSeed, and use that hash to pick one of the remaining slots. The proof of that pick is stored on your pull and shown on your order.
  6. We reveal the seed. When a chest sells out or is retired, the seed is published. From that moment the whole thing is checkable: the commitment, the shuffle and every pick. The verifier does it in your browser. Every pull also has its own proof page, linked from My pulls, with its hashes, a photo of the item and its value history.

Always-available chests

Always-available chests are restocked over time, so there is no fixed list to lock in. Instead the randomness is locked in: before the first rip we draw a secret seed and publish its hash. Each rip is rolled from that seed, the rip number and your browser's clientSeed, so we cannot choose or predict your roll.

always-available rips
h         = sha256(`unitedrips-open-v1|${seed}|${nonce}|${clientSeed}`)
roll      = int(h[0..13]) / 16^13            -> value range by the live odds, in published order
pick      = int(h[13..26]) mod itemsInRange  -> the item, items in range sorted by stock order

When a chest uses auto odds, the live odds are calculated at the moment of the rip from the product in the chest, using the published method, and they are the same for every buyer at that moment. Each pull stores the live odds, the roll, the range and the hash, and in a chest with odds modes, the mode you picked (the odds stored are that mode's odds). We publish the seed from time to time and whenever a chest is retired, and then every rip made with it can be checked: the hash must match, and the roll must land in the range you got.

The exact formulas

These are copied from the comments at the top of our fairness module. Version string: packrip-fairness-v1. All hashes are SHA-256 over UTF-8 text, printed as lowercase hex.

publish time
manifest      = JSON array of item ids, sorted (what is in the chest)
manifestHash  = sha256(manifest)
seed          = 32 random bytes (hex), kept secret until the chest sells out or retires
seedHash      = sha256(seed)
commitment    = sha256(`${version}|${seedHash}|${manifestHash}`)
order         = fisherYates(manifest, keystream(seed))   -> slot index i holds order[i]
purchase time (per unit)
nonce         = number of units sold in this chest before this one (0-based)
clientSeed    = entropy supplied by the buyer's browser (or empty string)
remaining     = sorted list of slot indexes still AVAILABLE
pick          = int(sha256(`${seed}|${nonce}|${clientSeed}`)) mod remaining.length
slotIndex     = remaining[pick]

Keystream and shuffle details

The shuffle needs a stream of random numbers that only depends on the seed. We use HMAC-SHA256 in counter mode and unbiased rejection sampling:

keystream
block(counter) = HMAC-SHA256(key = seed, message = String(counter))
each block yields eight 32-bit big-endian unsigned integers (4-byte steps)

nextInt(n):
  limit = floor(2^32 / n) * n
  take v from the stream until v < limit
  return v mod n

fisherYates(arr):
  for i from arr.length - 1 down to 1:
    j = nextInt(i + 1)
    swap arr[i], arr[j]

For the per-purchase pick we use the first 12 hex characters (48 bits) of the selection hash so the integer stays exact in JavaScript, then reduce it modulo the number of remaining slots. Slots are always considered in ascending index order so the same inputs give the same pick on any machine.

What this proves, and what it does not

Known limitation, stated plainly
We know the full slot order before any item is revealed, because we generated the seed. Commit-reveal proves we did not change the contents or the order after publishing, and it proves we did not choose which slot you got. It does not make us blind to the order.
  • The manifest cannot change. Adding, removing or swapping an item after publish would change the manifest hash and break the commitment.
  • The order cannot change. The seed determines the shuffle. A different seed would not hash to the published seed hash.
  • We cannot steer your slot. Your pick depends on your clientSeed, which we do not see until your order is placed and which is part of the proof. The nonce is the count of units sold before yours, serialized in the database, so we cannot reorder purchases either.
  • We cannot predict the next buyer's slot. Because the next buyer's clientSeed is random and unknown to us, we cannot know which slot they will get, so we cannot time our own purchases around good slots.
  • Owners and staff are prohibited from purchasing. This is a rule in our terms and an internal policy, not a mathematical guarantee. Anyone with access to the seed could, in principle, know the order; the clientSeed mechanism above is what stops that knowledge from being useful for picking a slot.
  • Slot picks are uniform. Every remaining slot has the same chance on every purchase. Our test suite checks this statistically.

Every published chest

Commitments are shown the moment a chest is published. The seed is returned by the verifier once the chest has sold out or been retired.

Custom chestRetiredSeed revealed
Verify
chest id
cmveomlki001dl808an5vvg70
version
unitedrips-open-v1
type
always available
commitment
06a87d8f47cc...dbf4aa
seedHash
508b74778219...5e71a6
published
Mon, 19 Oct 2026 03:15:54 GMT
revealed
Tue, 20 Oct 2026 03:20:30 GMT
Custom chestRetiredSeed revealed
Verify
chest id
cmveomksj003hii080bw4nntt
version
unitedrips-open-v1
type
always available
commitment
019fa8e00ed2...bf583f
seedHash
8b2f119fb532...985a9f
published
Mon, 19 Oct 2026 03:15:53 GMT
revealed
Tue, 20 Oct 2026 03:20:30 GMT
Custom chestRetiredSeed revealed
Verify
chest id
cmuifg9hx000xjw04xljscf6l
version
unitedrips-open-v1
type
always available
commitment
14e083759a21...281d44
seedHash
e3f21b19cfe4...85a9e6
published
Sat, 26 Sep 2026 13:30:24 GMT
revealed
Sun, 27 Sep 2026 13:30:45 GMT
chest id
cmug3nha3004ll504bpr8qone
version
unitedrips-open-v1
type
always available
commitment
6234a2171c72...98c73d
seedHash
f608d85d3a7e...688b6f
published
Thu, 24 Sep 2026 22:24:33 GMT
chest id
cmug3ngmq0038l504817f1xlx
version
unitedrips-open-v1
type
always available
commitment
027885620e3b...9b983a
seedHash
293b71a6dd51...20a325
published
Thu, 24 Sep 2026 22:24:33 GMT
Modern Pack RushLiveSeed sealed
Verify
chest id
cmug3nfvx0001l504ar6qpyv0
version
unitedrips-open-v1
type
always available
commitment
288afa5ce5d2...cb848d
seedHash
58380d0f1dd6...51265c
published
Thu, 24 Sep 2026 22:24:32 GMT
Booster Box CaseRetiredSeed revealed
Verify
chest id
cmuczrpoz00d2l804k4b94daq
version
packrip-fairness-v1
slots
19
commitment
38927a609907...11ce2f
seedHash
deb9082b8652...9da50d
manifestHash
c4c30a795920...7acbe5
published
Tue, 22 Sep 2026 18:12:33 GMT
revealed
Thu, 24 Sep 2026 22:16:34 GMT
Prismatic CaseRetiredSeed revealed
Verify
chest id
cmuczrp2j00c6l804a89p8wg6
version
packrip-fairness-v1
slots
14
commitment
390d692b0ca4...b296df
seedHash
5afcddd8a708...625960
manifestHash
81efddcd265a...58c7fd
published
Tue, 22 Sep 2026 18:12:33 GMT
revealed
Thu, 24 Sep 2026 22:16:34 GMT
151 CaseRetiredSeed revealed
Verify
chest id
cmuczrodj00b0l8048kuhrtss
version
packrip-fairness-v1
slots
16
commitment
66cd0c61bb62...edbb3a
seedHash
b0707b61cca8...320158
manifestHash
f5ba3c72eb15...6b963d
published
Tue, 22 Sep 2026 18:12:32 GMT
revealed
Thu, 24 Sep 2026 22:16:34 GMT
Pokemon GrailRetiredSeed revealed
Verify
chest id
cmubyu8iu00g7ic04w9ale2dy
version
packrip-fairness-v1
slots
2
commitment
405190c756ef...e30f53
seedHash
bb0b2eafe644...8d4145
manifestHash
5f0d8f618132...ee74dc
published
Tue, 22 Sep 2026 00:58:45 GMT
revealed
Thu, 24 Sep 2026 22:16:35 GMT
Pokemon GoldRetiredSeed revealed
Verify
chest id
cmubyu7we00fbic041m5l3akq
version
packrip-fairness-v1
slots
1
commitment
091d92b77d5d...6bd622
seedHash
80325c73f528...72cc3a
manifestHash
4e4cdd41fd6a...d03cd9
published
Tue, 22 Sep 2026 00:58:44 GMT
revealed
Thu, 24 Sep 2026 22:16:35 GMT
Pokemon StarterRetiredSeed revealed
Verify
chest id
cmubyu77f00e5ic045h5yxl3z
version
packrip-fairness-v1
slots
1
commitment
c195d2c82932...f20662
seedHash
d13c8d1dd36c...ea678d
manifestHash
0d66ed74927c...6ee166
published
Tue, 22 Sep 2026 00:58:44 GMT
revealed
Thu, 24 Sep 2026 22:16:35 GMT