Loading...
Loading...
Manage world permissions, namespaces, resource registration, and access control. Use when configuring world ownership, setting up authorization policies, or managing resource permissions.
npx skill4agent add dojoengine/book dojo-world"Grant writer permission to my system""List permissions for my world"World Owner (highest)
└── Namespace Owner
└── Resource Owner / Writer (lowest)dojo_<profile>.toml[writers]
# Namespace-level: actions can write to all resources in my_game
"my_game" = ["my_game-actions"]
# Resource-specific: movement can only write to Position
"my_game-Position" = ["my_game-movement"]
[owners]
# Namespace ownership
"my_game" = ["my_game-admin"]"<TARGET_TAG>" = ["<GRANTEE_TAG>"]# Grant writer permission
sozo auth grant writer my_game-Position,my_game-actions
# Grant owner permission
sozo auth grant owner my_game,my_game-admin# Revoke writer permission
sozo auth revoke writer my_game-Position,my_game-actions
# Revoke owner permission
sozo auth revoke owner my_game,my_game-admin# List all permissions
sozo auth listuse dojo::world::WorldStorage;
// Grant writer permission to a contract
world.grant_writer(
selector_from_tag!("my_game-Position"),
movement_system_address
);
// Grant owner permission
world.grant_owner(
selector_from_tag!("my_game-GameState"),
new_owner_address
);// Revoke writer permission
world.revoke_writer(
selector_from_tag!("my_game-Position"),
old_system_address
);
// Revoke owner permission
world.revoke_owner(
selector_from_tag!("my_game-GameState"),
old_owner_address
);// Check if address is owner
let is_owner = world.is_owner(resource_selector, address);
// Check if address is writer
let can_write = world.is_writer(resource_selector, address);// Good: Specific permissions for specific functions
world.grant_writer(selector_from_tag!("my_game-Position"), movement_contract);
world.grant_writer(selector_from_tag!("my_game-Health"), combat_contract);
// Bad: Overly broad permissions
world.grant_owner(selector_from_tag!("my_game"), movement_contract);// Different systems handle different aspects
world.grant_writer(selector_from_tag!("my_game-Position"), movement_system);
world.grant_writer(selector_from_tag!("my_game-Health"), combat_system);
world.grant_writer(selector_from_tag!("my_game-Inventory"), inventory_system);
// Trading system needs access to Inventory too
world.grant_writer(selector_from_tag!("my_game-Inventory"), trading_system);// This system can write to ANY resource in "my_game" namespace
world.grant_writer(
selector_from_tag!("my_game"),
system_contract
);// Admin has owner permission on namespace
world.grant_owner(selector_from_tag!("my_game"), game_admin);
// Admin has owner permission on critical resources
world.grant_owner(selector_from_tag!("my_game-GameConfig"), game_admin);fn spawn(ref self: ContractState) {
let mut world = self.world_default();
let player = get_caller_address();
// No permission check - anyone can spawn
world.write_model(@Position { player, vec: Vec2 { x: 0, y: 0 } });
}fn admin_function(ref self: ContractState) {
let mut world = self.world_default();
let caller = get_caller_address();
// Check caller is owner of the namespace
assert(
world.is_owner(selector_from_tag!("my_game"), caller),
'not authorized'
);
// Proceed with admin logic
}#[derive(Drop, starknet::Event)]
pub struct OwnerUpdated {
#[key]
pub resource: felt252,
#[key]
pub contract: ContractAddress,
pub value: bool,
}
#[derive(Drop, starknet::Event)]
pub struct WriterUpdated {
#[key]
pub resource: felt252,
#[key]
pub contract: ContractAddress,
pub value: bool,
}# dojo_dev.toml
[namespace]
default = "my_game"
[writers]
# All resources in my_game can be written by actions
"my_game" = ["my_game-actions"]
[owners]
# Admin system owns the namespace
"my_game" = ["my_game-admin"]fn add_new_system(ref self: ContractState, new_system_address: ContractAddress) {
let mut world = self.world_default();
// Must be namespace owner to grant permissions
world.grant_writer(
selector_from_tag!("my_game-Position"),
new_system_address
);
}fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) {
let mut world = self.world_default();
// Grant owner to new address
world.grant_owner(selector_from_tag!("my_game"), new_owner);
// Revoke from current owner
world.revoke_owner(selector_from_tag!("my_game"), get_caller_address());
}fn debug_permissions(world: @WorldStorage, resource: felt252, address: ContractAddress) {
let is_owner = world.is_owner(resource, address);
let is_writer = world.is_writer(resource, address);
// Log or print these values for debugging
}