project screenshot 1
project screenshot 2
project screenshot 3
project screenshot 4
project screenshot 5

BattleshipX

Secure On-chain Battleship using Nillion's Blind Computation and EthSign Attestations

BattleshipX

Created At

Scaling Ethereum 2024

Winner of

trophy

Nillion - Best novel use case of blind computation with Nillion

trophy

Arbitrum - Qualifying Arbitrum Submissions

Prize Pool

Project Description

BattleshipX is a secure and private battleship game that can be played with friends. It uses nillion for storing the game state and and blind computation for the game logic.

First user create a profile for the game, using a unique username. The profile is a custom implementation of ERC-7401: Parent-Governed Non-Fungible Tokens Nesting which brings nestable NFTs to Ethereum.

The main NFT is a on-chain profile NFT which has abilities to track users' game history, stats and other metadata. The profile NFT can have multiple child NFTs which are the game NFTs. These Game NFTs the Battleship Ships the user has eg- Battleship, Cruiser, Destroyer, Submarine and Carrier.

The game logic is computed using blind computation. The game state is stored in nillion. The game state is encrypted and stored in nillion

The game is played in a turn based manner made using Next.js, React DND, wagmi as the major tech stack. There are also custom solidity contracts for the profile and game management, and a minimal FastAPI server for interacting with nillion and the game.

The contracts have been deployed to Arbitrum Sepolia Testnet.

BattleshipX: 0xe86b1899376c77e1a109ea2124e462ef58e56897 BattleshipURI Library: 0x8f966BC6Ad2D241a01C1f7634C47c7419Ce96830

How it's Made

While storing the secret game state in nillion, it is stored as follows:

{ "carrier": [101, 102, 103, 104, 105], "battleship": [112, 113, 114, 115], "cruiser": [121, 122, 123], "submarine": [165, 175, 185], "destroyer": [191, 192] } where each number is 1XY where X is the row number and Y is the column number. The game state is stored in nillion in encrypted form. X and Y are in range of 0-9.

Why extra 1 at start? The extra 1 is added to make the number 3 digit as zero at the X position will be ignored by the game logic.

When a user attacks a position, the user sends the position to the contract.

For Example: User attacks position 7, 5. The contract will compute the attack with position 175, the computation starts at 1 and multiplies it by (value - position)

This is done through Array.reduce method. The logic is if there is a ship at that position, somewhere in the computation value == position and the result becomes 0. If the result is 0, the user has hit the ship.

background image mobile

Join the mailing list

Get the latest news and updates