Gaming has evolved significantly, from traditional board games to digital experiences, and now, to on-chain games — a completely new paradigm enabled by blockchain technology. As blockchain-based ecosystems flourish, particularly with the scaling solutions offered by layer 2 technologies, developers have begun exploring new business models, financial incentives, and decentralized ownership structures that were previously impossible.

In this article, we’ll explore the need for on-chain games, their advantages, and how Dojo Engine helps developers build provable, decentralized, and autonomous games faster than ever before.

Games have been integral to human history, from ancient board games like Chess and Go to modern digital experiences like World of Warcraft and Fortnite. However, the underlying structure of games has remained largely centralized — players interact with a game world owned and controlled by a central entity (developers, publishers, or platforms).

On-chain games introduce a revolutionary concept: games where both state and logic exist entirely on a blockchain. This means that:

  • The game’s rules and mechanics are enforced by smart contracts.
  • Players have true ownership over in-game assets.
  • The game state is public, auditable, and tamper-proof.
  • Games can be composable, allowing external developers to build on top of existing game worlds.

While traditional games rely on centralized servers and game economies controlled by publishers, on-chain games offer a radically different approach:

Unlike traditional games where financialization is often limited to NFTs, on-chain games integrate economic incentives and value transfer at their core. Players can earn, trade, and stake assets in ways that were previously impossible.

In traditional games, disputes over in-game assets or transactions rely on centralized authorities. On-chain games use the blockchain as an escrow and arbitrator, ensuring fairness and transparency.

On-chain gaming allows for atomic payouts, decentralized revenue sharing, and permissionless modding. Developers can monetize gameplay through programmable economies rather than relying on ads or in-game purchases.

The best games in history, such as DOTA and Counter-Strike, started as mods of existing games. On-chain games take this further by offering shared state and open APIs, allowing developers to create new game mechanics, spin-off games, and community-driven extensions.

Examples:

  • DOTA (originally a Warcraft 3 mod, now a billion-dollar franchise)
  • Counter-Strike (originally a Half-Life mod, now a leading FPS title)

On-chain games enable headless games, atomic payouts, and games as protocols, ushering in a new era of community-driven game development.

  • Loot Survivor Clients (players generate content in a shared game world)
  • DF Client Plugins (modular expansions built on top of existing games)

One of the biggest advantages of on-chain gaming is immutability and trustlessness.

  • Blockchains exist for escrow—this is their primary function.
  • On-chain games are impossible to cheat because game logic is enforced at the smart contract level.
  • High-stakes competitive games (with financial rewards) become possible without fear of exploitation.

A highly competitive real-time strategy (RTS) game where players stake assets before a match. Since all transactions and logic are on-chain, cheating is impossible, and winnings are automatically distributed based on game outcomes.


  • Low cost, easy to pick up and play
  • Baked-in token loops for rewards
  • Game Examples: RYO, Loot Survivor, Paved
  • Multiplayer & asynchronous mechanics
  • Session-based with buy-ins and rewards
  • Game Examples: Eternum, Sky Strife, Dark Forest, ZConquer
  • Decentralized and self-governing
  • No single entity owns the game
  • No fully autonomous world exists yet, but early prototypes are emerging

Dojo is an open-source, community-driven provable game engine designed to accelerate on-chain game development. Before Dojo, developers had to build their own indexers, contract architectures, and game clients from scratch.

With Dojo, developers can go from zero to a fully functional game in just a week.

  • Standardizes the development experience (DevX) for on-chain games
  • Simplifies on-chain state management via models
  • Minimizes boilerplate code
  • Provides powerful developer tooling

Dojo extends the Cairo compiler, injects macros, and creates a standardized ORM-like state management system. All states are stored in a World contract, and Dojo contracts mutate this state.

Dojo Architecture Overview

  • Provides the interface for on-chain worlds
  • Designed for composability and extensibility
  • Registers models that extend storage
  • Deploys contracts that extend logic
  • Manages access control for data modifications

To follow along, ensure you have:

  • Dojo installed (dojoup)
  • Sozo, Katana, Torii, and Origami installed
  • A basic understanding of Cairo and smart contract development
  • Sozo: Command-line tool for managing Dojo projects
  • Torii: Automatic indexer for your models (SQL/Postgres support)
  • Katana: Local devnet for testing game logic
  • Origami: Game development library with common patterns
  • BYO Client: Official clients in Dojo.js, Unity, C, and more

Building the Game: Red vs. Blue Team

We are developing Red vs. Blue Team, a map control game where players join either the Red or Blue team. Players can paint tiles on the game map and aim to maintain control of the most territory. However, each player is limited to one action every 60 seconds, making strategic tile placement critical.

To implement this game, we need:

  • Players will be identified using their wallet address.
  • Upon registration, a player selects a team (Red or Blue).
  • The game board consists of tiles, each defined by x and y keys.
  • Each tile has a color (either Red or Blue) to reflect the controlling team.
  • A new player joins the game by registering with their wallet address.
  • The player selects a team (Red or Blue).
  • A player selects a tile (x, y) to paint in their team’s color.
  • A cooldown prevents players from painting more than once every 60 seconds.
  • The team with the most painted tiles maintains control.

Contracts and client folders are self-explanatory. However, the key is understanding how we need to run each of them and how they are interlinked.

Please take a look at the source code here. I initialized the project using the Dojo starter kit.

The client (React+Vite) application can be run using

npm install
npm run dev

Then start the Katana local node with the following command:

katana --disable-fee --allowed-origins "*"

In another terminal window, navigate again to the contracts directory and build the contracts using Sozo, and apply the migrations to deploy the contracts:

sozo build 
sozo migrate apply

Start the Torii server, replacing 0x6457e5a40e8d0faf6996d8d0213d6ba2f44760606e110e03e3d239c5f769e87 with the actual world address if different:

torii --world 0x6457e5a40e8d0faf6996d8d0213d6ba2f44760606e110e03e3d239c5f769e87 --allowed-origins "*"

Models define data structures annotated with #[dojo::model] for integration into Dojo.

#[derive(Copy, Drop, Serde)]
#[dojo::model]
struct Tile {
    #[key]
    x: u16,
    #[key]
    y: u16,
    color: felt252
}
  • #[key] x, y: Primary keys for grid location.
  • color: felt252: Stores tile color.

Each tile represents a grid coordinate where players can paint.

const TIME_BETWEEN_ACTIONS: u64 = 120;

#[derive(Copy, Drop, Serde)]
#[dojo::model]
struct Player {
    #[key]
    address: starknet::ContractAddress,
    player: u32,
    last_action: u64
}

#[generate_trait]
impl PlayerImpl of PlayerTrait {
    fn check_can_place(self: Player) {
        if starknet::get_block_timestamp() - self.last_action < TIME_BETWEEN_ACTIONS {
            panic!("Not enough time has passed");
        }
    }
}
  • TIME_BETWEEN_ACTIONS: 120-second cooldown to prevent spam.
  • #[key] address: Primary key for player identity.
  • check_can_place(): Enforces action cooldown.

This structure ensures fair play by restricting frequent updates.

Contracts define the logic that enables players to take actions like spawning and painting tiles.

// define the interface
#[dojo::interface]
trait IActions {
    fn spawn();
    fn paint(x: u16, y: u16, color: felt252);
}

#[dojo::contract]
mod actions {
    use super::{IActions};
    use starknet::{ContractAddress, get_caller_address, get_block_timestamp};
    use boot_camp_paint::models::{tile::{Tile}, player::{Player}};

    #[abi(embed_v0)]
    impl ActionsImpl of IActions<ContractState> {
        fn spawn(world: IWorldDispatcher) {
            let address = get_caller_address();
            let player = world.uuid();
            let existing_player = get!(world, (player), Player);
            assert(existing_player.last_action == 0, "ACTIONS: player already exists");
            let last_action = get_block_timestamp();
            set!(world, Player { address, player, last_action });
        }

        fn paint(world: IWorldDispatcher, x: u16, y: u16, color: felt252) {
            let address = get_caller_address();
            let player = get!(world, (address), Player);
            assert(player.address == address, "ACTIONS: not player");
            set!(world, Tile { x, y, color });
        }
    }
}
  • IActions Interface: Defines the available actions: spawn() and paint(x, y, color).
  • spawn() Function:
    • Retrieves the caller’s address.
    • Generates a unique player ID.
    • Ensures the player doesn’t already exist.
    • Records the player in the world state.
  • paint() Function:
    • Retrieves the caller’s address.
    • Verifies the caller is an existing player.
    • Updates the tile color at the specified (x, y) coordinates.

This system ensures that only registered players can modify tiles and prevents duplicate player creation.

After running these contracts and building them, you should be able to spin up a local katana devnet.

Once you run the contracts on Katana, you should get a console log of the contract address. Save it for later.

Then you should be able to start a torii server in a new terminal using this command.

torii --world 0x6457e5a40e8d0faf6996d8d0213d6ba2f44760606e110e03e3d239c5f769e87 --allowed-origins "*"

Based on this, you should see a graphQL link on the terminal that you can access which will automatically generate schema for you.

Now, the only portion pending is frontend! Take a look at my older tutorial for the same.

Wola! This is all you need to get started with dojo-engine.

  1. https://book.dojoengine.org/tutorial/dojo-starter
  2. https://www.youtube.com/watch?v=xKYqFMibIB0
  3. https://www.youtube.com/watch?v=sj0lJjufby4