Manage world migrations, handle breaking changes, and upgrade Dojo versions. Use when updating deployed worlds, migrating to new versions, or handling schema changes.
80
Does it follow best practices?
If you maintain this skill, you can automatically optimize it using the tessl CLI to improve its score:
npx tessl skill review --optimize ./path/to/skillValidation for skill structure
Handle world migrations, upgrades, and breaking changes when updating deployed Dojo worlds.
Manages migration workflows:
Update existing world:
"Migrate my changes to the deployed world"Version upgrade:
"Upgrade my project to Dojo v1.8.0"sozo inspectShows:
sozo build
sozo test# Deploy with default dev profile
sozo migrate
# Deploy with specific profile
sozo migrate --profile sepoliaAdding new model:
// New model - safe to add
#[derive(Copy, Drop, Serde)]
#[dojo::model]
pub struct NewFeature {
#[key]
pub player: ContractAddress,
pub data: u32,
}Adding new system:
// New system - safe to add
#[dojo::contract]
pub mod new_system {
// Implementation
}Adding model field:
// Adding field - existing data will have default (zero) value
struct Position {
#[key] player: ContractAddress,
x: u32,
y: u32,
z: u32, // New field
}Changing key fields:
// Old
struct Position {
#[key] player: ContractAddress,
x: u32, y: u32,
}
// New - BREAKING! Different key structure
struct Position {
#[key] entity_id: u32, // Changed key
x: u32, y: u32,
}Removing fields:
// Old
struct Stats {
#[key] player: ContractAddress,
health: u8,
mana: u8,
}
// New - BREAKING! Data loss
struct Stats {
#[key] player: ContractAddress,
health: u8,
// mana removed
}Changing field types:
// Old
struct Position {
#[key] player: ContractAddress,
x: u32,
y: u32,
}
// New - BREAKING! Type incompatible
struct Position {
#[key] player: ContractAddress,
x: u128, // Changed type
y: u128,
}Deploy fresh world with different seed:
# dojo_dev.toml
[world]
seed = "my_game_v2" # Different seed = new world addresssozo build && sozo migrateKeep both old and new versions:
// Keep old model
#[derive(Copy, Drop, Serde)]
#[dojo::model]
pub struct PositionV1 {
#[key] player: ContractAddress,
x: u32, y: u32,
}
// Add new model
#[derive(Copy, Drop, Serde)]
#[dojo::model]
pub struct PositionV2 {
#[key] entity_id: u32,
x: u32, y: u32, z: u32,
}Create a migration system to transform data:
#[dojo::contract]
pub mod migrator {
fn migrate_positions(ref self: ContractState, players: Array<ContractAddress>) {
let mut world = self.world_default();
for player in players {
// Read old format
let old_pos: PositionV1 = world.read_model(player);
// Transform to new format
let new_pos = PositionV2 {
entity_id: world.uuid(),
x: old_pos.x,
y: old_pos.y,
z: 0,
};
// Write new format
world.write_model(@new_pos);
}
}
}Scarb.toml:[dependencies]
dojo = "1.8.0"
[dev-dependencies]
dojo_cairo_test = "1.8.0"Review changelog for breaking changes
Build and test:
sozo build
sozo testsozo migratesozo inspectsozo build)sozo test)sozo migrate)# 1. Add model to code
# 2. Build
sozo build
# 3. Migrate
sozo migrate
# 4. Verify
sozo inspect# 1. Update system code
# 2. Build and test
sozo build
sozo test
# 3. Migrate (redeploys system)
sozo migrate
# 4. Test updated system
sozo execute my_game-actions spawnsozo build firsttarget/ directory and rebuildsozo inspect outputAfter migration:
sozo build --typescript)dojo-indexer skill)3c1874f
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.