Rock-Paper-Scissors with Conditional Transactions
This comprehensive tutorial walks you through building a Rock-Paper-Scissors game that uses Conditional Transactions (CTX) to keep player moves encrypted until both players have committed. The game automatically decrypts moves onchain and determines the winner without any manual reveal phase.How the Game Works
The game implements a commit-reveal pattern with automatic decryption using CTX: Game Flow:This tutorial requires access to a CTX-enabled SKALE chain (SKALE Base or SKALE Base Sepolia). Check Programmable Privacy for current feature availability.
- Node.js 18+ and npm/yarn
- Wallet browser extension
- Access to a CTX-enabled SKALE chain
- Basic knowledge of Solidity and React
Step 1: Clone the Project
Clone the Rock-Paper-Scissors demo repository:- Foundry
- Frontend
Update Addresses: After deploying, copy the output addresses to your frontend
config/contracts.ts.Fund Your Wallet: After deployment, the script outputs the token address. Use a block explorer or cast to call
mint() on the MockSKL contract to get tokens for testing.Step 2: Smart Contract Overview
The core game logic is inRockPaperScissors.sol. Let’s break down the key components.
Game State Structure:
Precompiled.sol to interact with the Programmable Privacy precompiled contracts:
SUBMIT_CTX (0x...1B): Submits encrypted data for automatic decryptionENCRYPT_TE (0x...1C): Encrypts data using threshold encryption (not used directly - frontend encrypts)
- Player 1’s encrypted move is stored onchain
- Wager tokens are transferred to the contract
- Game enters
Createdstate with a 1-hour join deadline
- Both encrypted moves are packaged into
encryptedArgs - The Game ID is passed as plaintext for callback identification
Precompiled.submitCTX()returns the CTX sender address- 0.06 ETH is transferred to cover CTX execution costs
Step 3: Frontend Setup
Install Dependencies: Navigate to the frontend directory and install dependencies:@skalenetwork/bite package for encryption:
CreateGame.tsx- Handles game creation with move encryptionJoinGame.tsx- Handles game joining with CTX gas paymentconfig/contract.ts- Contract configurationApp.tsx- Main application layout
Step 4: CreateGame Component
TheCreateGame.tsx component handles game creation. Here are the key parts:
Privacy SDK Initialization:
- Move value (1-3) is converted to hex:
move.toString(16).padStart(2, '0') - Privacy SDK encrypts the hex string using threshold encryption
- Encrypted bytes are returned as a hex string for contract submission
- Check if token approval is needed (allowance vs wager amount)
- If needed, approve the contract to spend tokens
- Encrypt the move using the Privacy SDK
- Call
createGamewith encrypted move, wager amount, and token address
Step 5: JoinGame Component
TheJoinGame.tsx component handles joining an existing game. Key differences from CreateGame:
Fetching Game Details:
joinGame call includes value: CTX_GAS_PAYMENT (0.06 ETH) which is required for the CTX execution.
Step 6: Run the Application
http://localhost:5173 and:
- Connect Wallet - Connect your wallet to the SKALE Base Sepolia network
- Get Test Tokens - Visit the faucet to get gas tokens
- Play a Game - Select your move, set wager amount, and create
Resources:
- Privacy SDK: GitHub Repository
- Demo Repository: TheGreatAxios/ctxs
- Programmable Privacy Overview: Introduction
