Manual

Stack · spin · drop

Manual

Rules, mechanics, stack

Catris is guideline-feel Tetris with overflowing cat sprites. Stack cats, clear lines, post the run. Every 15 minutes the highest score takes 60% of the vault pot funded by the 3% letscash.fun trade tax — paid to a contract, never an EOA.

Launchpad
letscash.fun
X / Telegram
@catrisXYZ

The well

Visible field is 10 × 20 with two hidden spawn rows above. Seven tetrominoes deal from a shuffled bag. A ghost marks the landing row. Hold parks one piece; specials lose their curse when held.

Field
10 columns × 20 rows (+2 hidden)
Deal
7-bag, no triple-repeat of the same cat
Gravity
900 ms at L1, −72 ms per level, floor 70 ms
Lock delay
520 ms, up to 15 resets
DAS / ARR
160 ms delay, 38 ms repeat

Controls

Left / right
← → or A / D
Soft drop
↓ or S · +1 per row
Hard drop
Space · +2 per row, locks on landing
Rotate
↑ or Z / X / W
Hold
C · once per piece
Pause
P

On a phone the same six actions sit under the well. Soft drop is a press-and-hold; the rest are taps.

Scoring

Line clears scale with level. Combos add on top. A small clock bonus ticks while the run is alive.

Single
100 × level
Double
300 × level
Triple
500 × level
Quad
800 × level
Combo
+50 × combo × level
Clock
+10 every 10 seconds
Level
every 10 lines

Black cats

After 120 points a cursed piece can spawn (~16% roll, with a score- scaled cooldown). They are the original specials: same sprite, black fur, a rule that fights you.

Still
UNROTATABLE — spin is dead
Lazy
UNMOVABLE — no slide left or right
Pounce
HARD DROP — slams itself every frame

Hold strips the curse. The next piece from the bag is ordinary again.

Epochs and the arena

A run ends when a cat locks above the well. Post it with a handle. The shared board stores every score. If a wallet is connected the same run is signed with personal_sign (EIP-191) and sent to the keeper for the on-chain board.

Epoch
15 minutes (900 s)
Winner
highest posted score in the window
Prize
60% of that epoch’s vault harvest, in ETH
Drip
30% merkle-claimed by $CATRIS holders
Team
10% to the team wallet set at deploy

Stack

Client is TanStack Start + React 19 + Tailwind. The well is a canvas painter: original cat SVGs preloaded as blob URLs, drawn with the js13k overflow math so ears and tails spill the cell. Scores live in Postgres (Neon in prod, PGLite locally). Chain reads go through viem on Robinhood Chain.

Chain
Robinhood Chain 4663
RPC
https://rpc.mainnet.chain.robinhood.com
Launch
letscash.fun · 3% trade tax
Factory
0x5bd1Fbe78a78fe8236fa00CF48fbEBA74ae34661
Hook
0x75A54357D9C78a2Db19004a5FDc76c50F9242AEC
Ticker
CATRIS

Fee flow

Traders pay the 3% tax in ETH on the Uniswap v4 pool that letscash.fun opens at launch. No bonding curve. The creator stream is handed to the vault.

trade $CATRIS → 3% letscash.fun tax → hook claim → Vault 60 / 30 / 10 → epoch winner ETH, holder drip, team

Contracts

Two helpers, Solidity 0.8.24, Remix, 200 optimizer runs. Vault holds the pot and the split. Board holds epochs and signed scores. A 15-minute keeper harvests the creator stream, posts the winner, and publishes the drip merkle root.

  1. CatrisVault(teamWallet) — letscash.fun creator stream recipient. Download
  2. CatrisBoard — no constructor args. Download
  3. Vault: setBot(keeperEOA), then setMetadata("https://catris.xyz", "catrisXYZ", "https://github.com/catrisXYZ", "https://t.me/catrisXYZ").
  4. Board: setBot(keeperEOA), setVault(VAULT_CA).
  5. Launch on letscash.fun/launch: name Catris, symbol CATRIS, fee 3%, pair ETH. Then hand the creator stream to VAULT_CA with updateCreator and call setTokenCA(TOKEN_CA) on the vault.

Keeper and site env

Bot source: epoch-bot.mjs + package.json. Env: RPC_URL, BOT_PRIVATE_KEY, VAULT_CA, BOARD_CA, TOKEN_CA, MIN_CLAIM_ETH. Fund the keeper with ~0.1 ETH for gas.

After deploy set VITE_VAULT_CA, VITE_BOARD_CA, VITE_TOKEN_CA, VITE_KEEPER_URL. Until those exist the arcade still runs — scores live on the shared board, chain writes wait for the keeper.

  • Empty escrow no longer reverts — the keeper can poke claimFromEscrow every epoch.
  • Reentrancy lock on prize, drip, team, and escrow pulls.
  • Score signatures are personal_sign, the message wallets actually produce.