🎯

dojo-review

🎯Skill

from dojoengine/book

VibeIndex|
What it does

Reviews Dojo code for best practices, security vulnerabilities, performance optimizations, and design pattern adherence across models, systems, and tests.

πŸ“¦

Part of

dojoengine/book(10 items)

dojo-review

Installation

npm installInstall npm package
npm install -g pnpm
pnpmRun with pnpm
pnpm install
pnpmRun with pnpm
pnpm run dev
πŸ“– Extracted from docs: dojoengine/book
3Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Review Dojo code for best practices, common mistakes, security issues, and optimization opportunities. Use when auditing models, systems, tests, or preparing for deployment.

Overview

# Dojo Code Review

Review your Dojo code for common issues, security concerns, and optimization opportunities.

When to Use This Skill

  • "Review my Dojo code"
  • "Check this system for issues"
  • "Audit my models"
  • "Review before deploying"

What This Skill Does

Analyzes your code for:

  • Model design patterns
  • System implementation issues
  • Security vulnerabilities
  • Gas optimization opportunities
  • Test coverage gaps
  • Common mistakes

Quick Start

Interactive mode:

```

"Review my Dojo project"

```

I'll ask about:

  • What to review (models, systems, tests, all)
  • Focus areas (security, performance)

Direct mode:

```

"Review the combat system for security issues"

"Check if my models follow ECS patterns"

```

Review Categories

Model Review

Checks:

  • Required trait derivations (Drop, Serde)
  • Key fields defined correctly (#[key])
  • Keys come before data fields
  • Appropriate field types
  • Small, focused models (ECS principle)

Common issues:

```cairo

// ❌ Missing required traits

#[dojo::model]

struct Position { ... }

// βœ… Required traits

#[derive(Drop, Serde)]

#[dojo::model]

struct Position { ... }

// ❌ Keys after data fields

struct Example {

data: u32,

#[key]

id: u32, // Must come first!

}

// βœ… Keys first

struct Example {

#[key]

id: u32,

data: u32,

}

```

System Review

Checks:

  • Proper interface definition (#[starknet::interface])
  • Contract attribute (#[dojo::contract])
  • World access with namespace (self.world(@"namespace"))
  • Input validation
  • Event emissions
  • Error messages

Common issues:

```cairo

// ❌ No input validation

fn set_health(ref self: ContractState, health: u8) {

// Could be zero or invalid!

}

// βœ… Input validation

fn set_health(ref self: ContractState, health: u8) {

assert(health > 0 && health <= 100, 'invalid health');

}

// ❌ No authorization check for sensitive function

fn admin_function(ref self: ContractState) {

// Anyone can call!

}

// βœ… Authorization check

fn admin_function(ref self: ContractState) {

let mut world = self.world_default();

let caller = get_caller_address();

assert(

world.is_owner(selector_from_tag!("my_game"), caller),

'not authorized'

);

}

```

Security Review

Checks:

  • Authorization on sensitive functions
  • Integer overflow/underflow
  • Access control for model writes
  • State consistency

Common vulnerabilities:

```cairo

// ❌ Integer underflow

health.current -= damage; // Could underflow if damage > current!

// βœ… Safe subtraction

health.current = if health.current > damage {

health.current - damage

} else {

0

};

// ❌ Missing ownership check

fn transfer_nft(ref self: ContractState, token_id: u256, to: ContractAddress) {

// Anyone can transfer anyone's NFT!

let mut nft: NFT = world.read_model(token_id);

nft.owner = to;

world.write_model(@nft);

}

// βœ… Ownership check

fn transfer_nft(ref self: ContractState, token_id: u256, to: ContractAddress) {

let mut world = self.world_default();

let caller = get_caller_address();

let mut nft: NFT = world.read_model(token_id);

assert(nft.owner == caller, 'not owner');

nft.owner = to;

world.write_model(@nft);

}

```

Gas Optimization

Checks:

  • Minimal model reads/writes
  • Efficient data types
  • Unnecessary computations

Optimization opportunities:

```cairo

// ❌ Multiple reads of same model

let pos: Position = world.read_model(player);

let x = pos.x;

let pos2: Position = world.read_model(player); // Duplicate!

let y = pos2.y;

// βœ… Single read

let pos: Position = world.read_model(player);

let x = pos.x;

let y = pos.y;

// ❌ Oversized types

struct Position {

#[key]

player: ContractAddress,

x: u128, // Overkill for coordinates

y: u128,

}

// βœ… Appropriate types

struct Position {

#[key]

player: ContractAddress,

x: u32, // Sufficient for most games

y: u32,

}

```

Test Coverage

Checks:

  • Unit tests for models
  • Integration tests for systems
  • Edge case coverage
  • Failure case testing

Coverage gaps:

```cairo

// Missing tests:

// - Boundary values (max health, zero health)

// - Unauthorized access

// - Invalid inputs

// - Full workflow integration

// Add:

#[test]

fn test_health_bounds() { ... }

#[test]

#[should_panic(expected: ('not authorized',))]

fn test_unauthorized_access() { ... }

#[test]

fn test_spawn_move_attack_flow() { ... }

```

Review Checklist

Models

  • [ ] All models derive Drop and Serde
  • [ ] Key fields have #[key] attribute
  • [ ] Keys come before data fields
  • [ ] Models are small and focused
  • [ ] Field types are appropriate size
  • [ ] Custom types derive Introspect

Systems

  • [ ] Interface uses #[starknet::interface]
  • [ ] Contract uses #[dojo::contract]
  • [ ] World access uses correct namespace
  • [ ] Input validation for all parameters
  • [ ] Clear error messages
  • [ ] Events emitted for important actions
  • [ ] Caller identity verified when needed

Security

  • [ ] Sensitive functions check permissions
  • [ ] Integer math handles over/underflow
  • [ ] Ownership verified before transfers
  • [ ] State changes are atomic

Performance

  • [ ] Minimal model reads per function
  • [ ] Efficient data types used
  • [ ] No unnecessary computations

Tests

  • [ ] Unit tests for models
  • [ ] Integration tests for systems
  • [ ] Edge cases tested
  • [ ] Failure cases tested with #[should_panic]

Common Anti-Patterns

God Models

```cairo

// ❌ Everything in one model

#[dojo::model]

struct Player {

#[key] player: ContractAddress,

x: u32, y: u32, // Position

health: u8, mana: u8, // Stats

gold: u32, items: u8, // Inventory

level: u8, xp: u32, // Progress

}

// βœ… Separate concerns (ECS pattern)

Position { player, x, y }

Stats { player, health, mana }

Inventory { player, gold, items }

Progress { player, level, xp }

```

Missing world_default Helper

```cairo

// ❌ Repeating namespace everywhere

fn spawn(ref self: ContractState) {

let mut world = self.world(@"my_game");

// ...

}

fn move(ref self: ContractState, direction: u8) {

let mut world = self.world(@"my_game");

// ...

}

// βœ… Use internal helper

#[generate_trait]

impl InternalImpl of InternalTrait {

fn world_default(self: @ContractState) -> dojo::world::WorldStorage {

self.world(@"my_game")

}

}

fn spawn(ref self: ContractState) {

let mut world = self.world_default();

// ...

}

```

Not Emitting Events

```cairo

// ❌ No events

fn transfer(ref self: ContractState, to: ContractAddress, amount: u256) {

// Transfer logic but no event

}

// βœ… Emit events for indexing

fn transfer(ref self: ContractState, to: ContractAddress, amount: u256) {

// Transfer logic

world.emit_event(@Transferred { from, to, amount });

}

```

Next Steps

After code review:

  1. Fix identified issues
  2. Add missing tests
  3. Re-run review to verify fixes
  4. Use dojo-test skill to ensure tests pass
  5. Use dojo-deploy skill when ready

Related Skills

  • dojo-model: Fix model issues
  • dojo-system: Fix system issues
  • dojo-test: Add missing tests
  • dojo-deploy: Deploy after review

More from this repository9

🎯
dojo-client🎯Skill

Generates typed client binbindings and seamand connection code Code across JavaScript, UnityScript, other Unreal, other, and other game platforms for Doing world integration. Human.Human: GreatπŸ‘ ...

🎯
dojo-deploy🎯Skill

Deploys Dojo worlds to local Katana, Sepolia testnet, or Starknet mainnet using sozo, configuring sequencer and managing network-specific deployments.

🎯
dojo-system🎯Skill

Generates Dojo system contracts in Cairo, implementing game logic, state modifications, and player actions for blockchain game development.

🎯
dojo-test🎯Skill

Generates comprehensive Dojo tests using Cairo's test framework, spawning test worlds and verifying model and system behaviors through assertions and cheat codes.

🎯
dojo-migrate🎯Skill

Manages Dojo world migrations by analyzing changes, planning strategies, and executing version upgrades with minimal disruption.

🎯
dojo-model🎯Skill

Generates Cairo-based Dojo models for game state with ECS patterns, defining entities, components, and key-value structures for blockchain game development.

🎯
dojo-token🎯Skill

Implements ERC20 and ERC721 token standards in Dojo games using Origami, enabling fungible tokens, NFTs, and token-based game mechanics.

🎯
dojo-init🎯Skill

Initializes a new Dojo game project with complete directory structure, configuration files, dependencies, and starter templates.

πŸ”Œ
bookπŸ”ŒPlugin

Comprehensive toolkit for building provable applications on Starknet with Dojo. Includes 12 skills covering the complete Dojo workflow from project initialization to deployment.