🎯

dojo-token

🎯Skill

from dojoengine/book

VibeIndex|
What it does

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

πŸ“¦

Part of

dojoengine/book(10 items)

dojo-token

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

Implement ERC20 and ERC721 token standards in Dojo using Origami library. Use when adding fungible tokens, NFTs, or token-based game mechanics.

Overview

# Dojo Token Standards

Implement ERC20 fungible tokens and ERC721 NFTs in your Dojo game using the Origami library.

When to Use This Skill

  • "Implement ERC20 token for game currency"
  • "Create NFT items with ERC721"
  • "Add token standard to my game"
  • "Use Origami for tokens"

What This Skill Does

Implements token standards:

  • ERC20 fungible tokens (currency, resources)
  • ERC721 non-fungible tokens (items, characters)
  • Token minting and burning
  • Transfer mechanics
  • Balance tracking

Token Standards

ERC20 - Fungible Tokens

For interchangeable assets:

  • Game currency (gold, gems)
  • Resources (wood, stone)
  • Experience points

Properties:

  • Divisible (can have fractions)
  • Interchangeable (any token = any other)
  • Track balances per account

ERC721 - Non-Fungible Tokens

For unique assets:

  • Character NFTs
  • Equipment/items
  • Land plots
  • Achievements

Properties:

  • Unique (each has token ID)
  • Indivisible (whole units only)
  • Individual ownership tracking

Using Origami Library

Installation

Add to Scarb.toml:

```toml

[dependencies]

origami_token = { git = "https://github.com/dojoengine/origami", tag = "v1.0.0" }

```

Origami provides reusable token components following standard interfaces.

Refer to the [Origami documentation](https://github.com/dojoengine/origami) for the latest API.

Simple Token Implementation

You can implement tokens using standard Dojo models without Origami:

ERC20-like Currency

```cairo

#[derive(Copy, Drop, Serde)]

#[dojo::model]

pub struct Gold {

#[key]

pub player: ContractAddress,

pub amount: u256,

}

#[starknet::interface]

trait IGoldToken {

fn mint(ref self: T, to: ContractAddress, amount: u256);

fn transfer(ref self: T, to: ContractAddress, amount: u256);

fn balance_of(self: @T, account: ContractAddress) -> u256;

}

#[dojo::contract]

mod gold_token {

use super::{IGoldToken, Gold};

use starknet::{ContractAddress, get_caller_address};

use dojo::model::ModelStorage;

#[abi(embed_v0)]

impl GoldTokenImpl of IGoldToken {

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

let mut world = self.world_default();

let mut balance: Gold = world.read_model(to);

balance.amount += amount;

world.write_model(@balance);

}

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

let mut world = self.world_default();

let from = get_caller_address();

let mut from_balance: Gold = world.read_model(from);

let mut to_balance: Gold = world.read_model(to);

assert(from_balance.amount >= amount, 'insufficient balance');

from_balance.amount -= amount;

to_balance.amount += amount;

world.write_model(@from_balance);

world.write_model(@to_balance);

}

fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {

let world = self.world_default();

let balance: Gold = world.read_model(account);

balance.amount

}

}

#[generate_trait]

impl InternalImpl of InternalTrait {

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

self.world(@"my_game")

}

}

}

```

ERC721-like NFT

```cairo

#[derive(Copy, Drop, Serde)]

#[dojo::model]

pub struct Weapon {

#[key]

pub token_id: u256,

pub owner: ContractAddress,

pub damage: u32,

pub rarity: u8,

}

#[starknet::interface]

trait IWeaponNFT {

fn mint(ref self: T, to: ContractAddress, damage: u32) -> u256;

fn transfer(ref self: T, to: ContractAddress, token_id: u256);

fn owner_of(self: @T, token_id: u256) -> ContractAddress;

}

#[dojo::contract]

mod weapon_nft {

use super::{IWeaponNFT, Weapon};

use starknet::{ContractAddress, get_caller_address};

use dojo::model::ModelStorage;

#[abi(embed_v0)]

impl WeaponNFTImpl of IWeaponNFT {

fn mint(ref self: ContractState, to: ContractAddress, damage: u32) -> u256 {

let mut world = self.world_default();

let token_id: u256 = world.uuid().into();

let weapon = Weapon {

token_id,

owner: to,

damage,

rarity: 1,

};

world.write_model(@weapon);

token_id

}

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

let mut world = self.world_default();

let from = get_caller_address();

let mut weapon: Weapon = world.read_model(token_id);

assert(weapon.owner == from, 'not owner');

weapon.owner = to;

world.write_model(@weapon);

}

fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress {

let world = self.world_default();

let weapon: Weapon = world.read_model(token_id);

weapon.owner

}

}

#[generate_trait]

impl InternalImpl of InternalTrait {

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

self.world(@"my_game")

}

}

}

```

Game Patterns

In-Game Currency

```cairo

// Award gold for completing quest

fn complete_quest(ref self: ContractState, quest_id: u32) {

let mut world = self.world_default();

let player = get_caller_address();

// Check quest is completed

// ...

// Award gold

let mut gold: Gold = world.read_model(player);

gold.amount += 100;

world.write_model(@gold);

}

// Spend gold to buy item

fn buy_item(ref self: ContractState, item_id: u32, price: u256) {

let mut world = self.world_default();

let player = get_caller_address();

let mut gold: Gold = world.read_model(player);

assert(gold.amount >= price, 'insufficient gold');

gold.amount -= price;

world.write_model(@gold);

// Give item to player

// ...

}

```

Multiple Resource Types

```cairo

#[derive(Copy, Drop, Serde)]

#[dojo::model]

pub struct Resources {

#[key]

pub player: ContractAddress,

pub wood: u256,

pub stone: u256,

pub iron: u256,

}

```

Equipment NFTs

```cairo

fn equip_weapon(ref self: ContractState, token_id: u256) {

let mut world = self.world_default();

let player = get_caller_address();

// Check ownership

let weapon: Weapon = world.read_model(token_id);

assert(weapon.owner == player, 'not owner');

// Equip

let mut equipment: Equipment = world.read_model(player);

equipment.weapon_id = token_id;

world.write_model(@equipment);

}

```

Token Events

```cairo

#[derive(Copy, Drop, Serde)]

#[dojo::event]

pub struct TokenTransferred {

#[key]

pub from: ContractAddress,

#[key]

pub to: ContractAddress,

pub amount: u256,

}

#[derive(Copy, Drop, Serde)]

#[dojo::event]

pub struct NFTTransferred {

#[key]

pub token_id: u256,

pub from: ContractAddress,

pub to: ContractAddress,

}

// Emit in your functions

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

```

Considerations

  • Balance checks: Always verify sufficient balance before transfers
  • Ownership: Always verify ownership before NFT operations
  • Overflow: Use u256 for token amounts to avoid overflow
  • Events: Emit events for all token operations for indexing
  • Permissions: Grant writer permission to token contracts

Next Steps

After implementing tokens:

  1. Test thoroughly with dojo-test skill
  2. Deploy with dojo-deploy skill
  3. Integrate with client (dojo-client skill)
  4. Set up permissions (dojo-world skill)

Related Skills

  • dojo-model: Token models extend Dojo models
  • dojo-system: Token logic in systems
  • dojo-test: Test token operations
  • dojo-review: Audit token implementation

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-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-review🎯Skill

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

🎯
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-deploy🎯Skill

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

🎯
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.