Page cover image

Exercise #3: CCIP Tic Tac Toe

Let's play a cross-chain game

Getting started

For the final example of this Masterclass, we are going to deploy and play the CCIP Tic Tac Toe game.

To play the game, we will need to deploy the TicTacToe smart contract on two different blockchains. By sending a transaction on the source chain, which can be either "start" or "move," the state of the game board will be modified, and these states will be "synchronized" by Chainlink CCIP on the other chain.

It is developed using Hardhat, so you will need to prepare the environment by cloning the repository from GitHub by running the following command:

git clone https://github.com/smartcontractkit/ccip-tic-tac-toe

Then install packages:

npm install

And finally, compile smart contracts:

npx hardhat compile

Set environment variables

We are going to use the @chainlink/env-enc package for extra security. It encrypts sensitive data instead of storing them as plain text in the .env file by creating a new .env.enc file. Although pushing this file online is not recommended, if that accidentally happens, your secrets will still be encrypted.

Set a password for encrypting and decrypting the environment variable file. You can change it later by typing the same command.

npx env-enc set-pw

Now set the following environment variables:

PRIVATE_KEY=""
ETHEREUM_SEPOLIA_RPC_URL=""
OPTIMISM_GOERLI_RPC_URL=""
ARBITRUM_TESTNET_RPC_URL=""
AVALANCHE_FUJI_RPC_URL=""
POLYGON_MUMBAI_RPC_URL=""

To set these variables, type the following command and follow the instructions in the terminal:

npx env-enc set

After you are done, the .env.enc file will be automatically generated.

If you want to validate your inputs, you can always run the next command:

npx env-enc view

Deploy TicTacToe smart contract

npx hardhat run ./scripts/deployTicTacToe.ts --network <blockchain>
npx hardhat run ./scripts/deployTicTacToe.ts --network <blockchain>

Where the list of supported chains consists of (case sensitive):

  • ethereumSepolia

  • optimismGoerli

  • arbitrumTestnet

  • avalancheFuji

  • polygonMumbai

For example, if you want to deploy contracts to Ethereum Sepolia and Avalanche Fuji, run the following commands:

npx hardhat run ./scripts/deployTicTacToe.ts --network ethereumSepolia
npx hardhat run ./scripts/deployTicTacToe.ts --network avalancheFuji

Transfer native tokens to the TicTacToe smart contract

After the deployment of the contract, you must transfer native tokens to these two contracts, respectively.

For example, if you deployed contracts to Avalanche Fuji and Ethereum Sepolia, please transfer 2 AVAX and 0.01 ETH to contracts on Avalanche Fuji and Ethereum Sepolia, respectively.

Update router

Please use the commands below to update the Router address for ccipSend.

npx hardhat ttt-update-router --blockchain ethereumSepolia --contract <address of TicTacToe on Ethereum Sepolia> --router 0xd0daae2231e9cb96b94c8512223533293c3693bf
npx hardhat ttt-update-router --blockchain avalancheFuji --contract <address of TicTacToe on Avalanche Fuji> --router 0x554472a2720e5e7d5d3c817529aba05eed5f82d8

Router addresses are listed below:

  • Ethereum Sepolia: 0xd0daae2231e9cb96b94c8512223533293c3693bf

  • Polygon Mumbai: 0x70499c328e1e2a3c41108bd3730f6670a44595d1

  • Optimism Goerli: 0xeb52e9ae4a9fb37172978642d4c141ef53876f26

  • Avalanche Fuji: 0x554472a2720e5e7d5d3c817529aba05eed5f82d8

  • Arbitrum Goerli: 0x88e492127709447a5abefdab8788a15b4567589e

Player 1 starts a game

You can start a new game through a TicTacToe contract on any chain. The player who starts a game is player 1. Player 1 needs to send a transaction to create a session, allowing the other player on the other chain to join that session and make a move.

Start a game with the command below:

npx hardhat ttt-start --source-blockchain ethereumSepolia --sender <address of TicTacToe on Ethereum Sepolia> --destination-blockchain avalancheFuji --receiver <address of TicTacToe on Avalanche Fuji>

You will see the message below in the terminal, and that means the message is sent by CCIP.

✅ Message sent, game session created! transaction hash: 0x1f65e17eef0fd9664c389d825db317ec385fe5b1f79baa62aded05583f980e1a

While the message is sent to CCIP, the status will not be synced until the message is finalized on the source chain and written into the contract on the other chain. Check the information in CCIP Explorer and find the message below to make sure the message is sent to the dest chain.

Get session ID by index

In order to join a game, a player needs to know the session ID of the game.

Get the session ID of the game by index with the command below:

npx hardhat ttt-get-sessionId --blockchain ethereumSepolia --contract <address of TicTacToe on Ethereum Sepolia> --index 0

Player 2 makes a move in Blockchain 2

Player 2, on the other chain, can make a move within the game session. The player needs to select a position with x and y coordinates(the range of x and y are from 0 to 2) with the command below:

npx hardhat ttt-move --x <x coordinate> --y <y coordinate> --player 2 --session-id <sessionId> --source-blockchain avalancheFuji --sender <address of TicTacToe on Avalanche Fuji> --destination-blockchain ethereumSepolia --receiver <address of TicTacToe on Ethereum Sepolia>

The x and y are coordinates on the board. eg:

Player 1 makes a move in Blockchain 1

After player 2 made the move, player 1 can make the move with x and y coordinates. Please note that transaction will fail if the position represented by x and y coordinates is occupied.

Player 1 makes a move with the command below:

npx hardhat ttt-move --x <x coordinate> --y <y coordinate> --player 2 --session-id <sessionId> --source-blockchain ethereumSepolia --sender <address of TicTacToe on Ethereum Sepolia> --destination-blockchain avalancheFuji --receiver <address of TicTacToe on Avalanche Fuji>

Repeat the previous two steps until the game is over

Repeat the previous two steps until either combination of player 1 or player 2 matches a winning combination.

Check the winner

Check the winner by command:

npx hardhat ttt-check-winner --blockchain ethereumSepolia --contract <address of TicTacToe on Ethereum Sepolia> --session-id <sessionId>

You can also check the winner from the contract on the other blockchain with the command:

npx hardhat ttt-check-winner --blockchain avalancheFuji --contract <address of TicTacToe on Avalanche Fuji> --session-id <sessionId>

Front-end of Tic-Tac-Toe

This project has a frontend implementation of a decentralized, multiplayer Tic-Tac-Toe game built with React, Wagmi, and Alchemy SDK.

Features

  • The game state is stored in the blockchain, enabling transparent and trustless gameplay.

  • Real-time interaction between two players from different blockchain networks.

  • Responsive design for a comfortable gaming experience on various devices.

  • An integrated game log to inform users about the game's progress.

Run

Change the directory by running the following command:

cd frontend

Install the dependencies:

npm install

Start the local server:

npm run dev

You can now access the application at the http://localhost:3000 in your browser.

Last updated