Skip to content

Venues — Guest-List Rotation

TL;DR: _list[UserToken] holds a block.timestamp + 1 days stamp. Refresh every 23 hours, not every 25. CROWS holders (25+) bypass the guest list entirely at QINGs with NoCROWS = false.

Why this matters

The 1-day TTL on guest-list entries is the finest-grained timer in player-visible Dysnomia, and it runs hot — anyone chatting regularly at a paid venue will trip it daily. Miss the window by a single block and the next Chat reverts with PayCover, or the next Join re-charges your wallet. Budget your days around it.

The numbers

From QING:

// Join
if CoverCharge > 0 and _list[UserToken] < block.timestamp:
    Asset.transferFrom(msg.sender, address(this), CoverCharge)
_list[UserToken] = block.timestamp + 1 days

// Chat
if CoverCharge != 0 and !(_list[UserToken] > block.timestamp):
    revert PayCover
Event Effect
Fresh Join (stale stamp) Pay CoverCharge; _list set to now + 1 days.
Repeat Join within 1 day No charge; _list overwritten to now + 1 days (extends the window).
Chat while stamp valid Free; no list mutation.
Chat while stamp expired, CoverCharge > 0 Revert PayCover.
Chat while CoverCharge == 0 Free; no list check.

Implication: Join resets the stamp even if you don't need to. Re-Joining at day 0.5 extends to day 1.5. There's no penalty for over-eager Join; there's only a gas cost.

CROWS bypass

From QING.bouncer:

  • If NoCROWS == false && CROWS.balanceOf(cBouncer) >= 25 * 10^18 → the holder is a bouncer.
  • Bouncers bypass some access-control paths, but Chat itself checks Admitted(UserToken) which reads _list. A CROWS holder still needs a fresh _list stamp to Chat.

So CROWS gets you bouncer powers (setting cover, managing guest list), not a chat-exemption.

Staff and guestlist

Bouncers can setGuestlist(addr) to write a _list stamp of block.timestamp + 1 days for any address — no Asset transfer required. Great for comped members.

The play

  1. Re-Join at the 23-hour mark, not the 24.5-hour mark. Avoid any risk of your next Chat reverting on the cover check.
  2. Script your Join cadence. If you're farming a paid venue, the Join is a fixed daily cost (unless you're guestlisted). Treat it as a subscription. If the cover drops below your expected daily MAI, you're in the green.
  3. Ask the bouncer for guestlist status. A venue that wants regular chatters should setGuestlist(addr) for known farmers. No cover, no rotation needed — you just need to re-Join daily to refresh _list.
  4. (inferred) Stack 25+ CROWS if you plan to run or moderate a venue. That's the single threshold for auto-bouncer eligibility at default-configured QINGs.
  5. If you're a venue owner, removeGuest(addr) is your manual eviction. Clears _list[addr] so their next Join re-pays cover (or blocks them if cover is high).
  6. Don't leave, then re-Join unnecessarily. There's no explicit Leave; you just stop chatting. But Join during a valid-stamp window is free, so re-Joining preemptively at 23h is perfectly fine.

Worked example

A QING has cover = 5 X. You start fresh.

  • Day 0, 10am: Join(YourLAU). Pay 5 X. _list[YourLAU] = 10am tomorrow.
  • Day 0, 11am – Day 1, 9:59am: Chat freely.
  • Day 1, 9am (23h mark): Join(YourLAU). Stamp still valid (10am > 9am), so no cover paid. _list[YourLAU] = 9am on Day 2.
  • Day 1, 11am onward: Chat freely for another 22 hours.
  • Day 2, 8:30am: Join(YourLAU). Still valid. Free.

You chatted all weekend for 5 X (one cover payment). If you'd Join'd on Day 1 at 11am instead (25h after first Join), cover would have been re-charged: 10 X total.

The cost of forgetting to refresh early: exactly CoverCharge per missed refresh.

Gotchas

  • The stamp is keyed by UserToken address, not by Soul. If you have multiple LAUs (unusual but possible), each one needs its own Join.
  • Comparisons are strict. _list[UserToken] > block.timestamp — an exact-equal stamp fails the check. If you want certainty, refresh at 23h, not at 24h.
  • setGuestlist is bouncer-only. You can't self-guestlist unless you're a bouncer at that venue.
  • removeGuest wipes the stamp, and the wiped entity must re-Join (and probably re-pay cover).
  • (inferred) 24h drift. PulseChain has ~10-second blocks. 1 days = 86400 seconds, so exactly 8640 blocks. Re-Join 100 blocks early (16 minutes) for a safe margin.
  • CROWS ≥ 25 doesn't skip the cover. The CROWS gate checks bouncer status; it doesn't short-circuit the cover-charge check in Join. You still pay cover unless you're guestlisted.

Where it cross-connects