dojo-review

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

9 stars

Best use case

dojo-review is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

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

Teams using dojo-review should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/dojo-review/SKILL.md --create-dirs "https://raw.githubusercontent.com/cartridge-gg/nums/main/.agents/skills/dojo-review/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/dojo-review/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How dojo-review Compares

Feature / Agentdojo-reviewStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

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

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# 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

Related Skills

dojo

9
from cartridge-gg/nums

Dojo Engine framework patterns — World, Systems, Models, Events, Components, Store, permissions, testing with spawn_test_world, and deployment with sozo.

dojo-world

9
from cartridge-gg/nums

Manage world permissions, namespaces, resource registration, and access control. Use when configuring world ownership, setting up authorization policies, or managing resource permissions.

dojo-token

9
from cartridge-gg/nums

Implement, deploy, and index ERC20 and ERC721 tokens in Dojo. Use when adding token contracts, deploying them, or configuring Torii to index balances and transfers.

dojo-test

9
from cartridge-gg/nums

Write tests for Dojo models and systems using spawn_test_world, cheat codes, and assertions. Use when testing game logic, verifying state changes, or ensuring system correctness.

dojo-system

9
from cartridge-gg/nums

Create Dojo systems that implement game logic, modify model state, and handle player actions. Use when implementing game mechanics, player commands, or automated logic.

dojo-model

9
from cartridge-gg/nums

Create Dojo models for storing game state with proper key definitions, trait derivations, and ECS patterns. Use when defining game entities, components, or state structures.

dojo-migrate

9
from cartridge-gg/nums

Manage world migrations, handle breaking changes, and upgrade Dojo versions. Use when updating deployed worlds, migrating to new versions, or handling schema changes.

dojo-init

9
from cartridge-gg/nums

Initialize new Dojo projects with proper directory structure, configuration files, and dependencies. Use when starting a new Dojo game project or setting up the initial project structure.

dojo-indexer

9
from cartridge-gg/nums

Set up and configure Torii indexer for GraphQL queries, gRPC subscriptions, and SQL access. Use when indexing your deployed world for client queries or real-time updates.

dojo-config

9
from cartridge-gg/nums

Configure Scarb.toml, dojo profiles, world settings, and dependencies. Use when setting up project configuration, managing dependencies, or configuring deployment environments.

dojo-architecture

9
from cartridge-gg/nums

Shinigami architecture for fully onchain Dojo games — Elements, Types, Models, Components, Systems, Helpers, Store, Events, Interfaces. Use when structuring a new game, adding modules, understanding the codebase hierarchy, or implementing new game mechanics.

ui-ux-pro-max

9
from cartridge-gg/nums

UI/UX design intelligence for web and mobile. Includes 50+ styles, 161 color palettes, 57 font pairings, 161 product types, 99 UX guidelines, and 25 chart types across 10 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui, and HTML/CSS). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, and check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, and mobile app. Elements: button, modal, navbar, sidebar, card, table, form, and chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, and flat design. Topics: color systems, accessibility, animation, layout, typography, font pairing, spacing, interaction states, shadow, and gradient. Integrations: shadcn/ui MCP for component search and examples.