Achievements
Proof-of-play NFTs that commemorate player milestones and accomplishments.
Purpose
Achievements are on-chain NFTs that prove a player accomplished something specific in gameplay. They serve as:
- Reputation markers — visible proof of skill or dedication
- Access gates — required for certain game modes, guilds, or features
- Historical records — permanent, verifiable gameplay accomplishments
- Collectibles — players collect and display them
Soulbound vs Transferable
| Type | Can Transfer? | Use Case |
|---|---|---|
| Soulbound | No | Skill-based accomplishments (prove YOU did it) |
| Transferable | Yes | Event participation, collectible milestones |
Default recommendation: Soulbound. If an achievement can be bought rather than earned, it loses its value as a reputation signal.
Achievement Types
Milestone Achievements
Awarded for reaching cumulative thresholds:
[
{ type_id: 1, name: "First Blood", condition: "wins >= 1" },
{ type_id: 2, name: "Veteran", condition: "wins >= 100" },
{ type_id: 3, name: "Legendary", condition: "wins >= 1000" },
{ type_id: 4, name: "Season Champion", condition: "season_rank == 1" },
{ type_id: 5, name: "Undefeated", condition: "streak >= 20" }
]
Season Achievements
Awarded for performance within a specific season:
[
{ type_id: 10, name: "Diamond Season 1", condition: "season_1_league == diamond" },
{ type_id: 11, name: "Top 10 Season 1", condition: "season_1_rank <= 10" }
]
Event Achievements
Awarded for participation or placement in special events:
[
{ type_id: 20, name: "Blitz Participant", condition: "event_blitz_001_participated" },
{ type_id: 21, name: "Blitz Champion", condition: "event_blitz_001_rank == 1" }
]
Minting Flow
GAME SERVER BLOCKCHAIN
═══════════ ══════════
Player reaches milestone
│
▼
Server checks achievement rules
│
▼
Server signs attestation:
{ player, type_id, nonce, timestamp }
│
▼
Attestation sent to player client
│ ┌──────────────────┐
▼ │ Achievement │
Player calls mint() ────────────────►│ Contract │
with attestation │ │
│ 1. verify sig │
│ 2. check nonce │
│ 3. mint NFT │
│ 4. mark used │
└──────────────────┘
Who pays gas?
| Model | Description |
|---|---|
| Player pays | Player submits the mint transaction (recommended for low-gas chains) |
| Server pays | Server submits on behalf of player (better UX, higher cost) |
| Lazy mint | NFT recorded off-chain, minted on-chain only when player requests |
Contract Interface
interface IAchievements {
// Mint a new achievement
function mint(
uint256 typeId,
uint256 nonce,
bytes calldata serverSignature
) external returns (uint256 tokenId);
// View
function hasAchievement(address player, uint256 typeId) external view returns (bool);
function getAchievements(address player) external view returns (uint256[] memory typeIds);
function getAchievementMetadata(uint256 typeId) external view returns (string memory uri);
}
Metadata
Achievement NFTs use standard ERC-721 metadata:
{
"name": "Season 1 Champion",
"description": "Achieved rank 1 in Season 1 of Monsuta Core",
"image": "ipfs://Qm.../season_1_champion.png",
"attributes": [
{ "trait_type": "Season", "value": "1" },
{ "trait_type": "Rank", "value": "1" },
{ "trait_type": "League", "value": "Diamond" },
{ "trait_type": "Earned On", "value": "2026-06-30" },
{ "trait_type": "Soulbound", "value": "true" }
]
}
Integration Guide
- Define achievement types — what should players be recognized for?
- Implement rule checking — server-side logic that detects when a player qualifies
- Generate attestations — server signs a packet authorizing the mint
- Deploy contract — ERC-721 with server-authorized minting
- Build UI — display earned achievements, mint pending ones, show collection
- Optional: gate access — use achievement ownership to unlock game features