Overview
This document provides a comprehensive reference for all functions available in the ZKScore Achievement Registry contract. Each function includes detailed parameter descriptions, return values, gas estimates, and usage examples.
All functions that modify state require a transaction and will consume gas. View functions are free to call and return data immediately.
Achievement Management Functions
createAchievement
Create a new achievement in the registry.
function createAchievement(
string memory name,
string memory description,
string memory imageURI,
uint8 category,
Rarity rarity,
uint256 points,
uint256 scoreBoost,
RequirementType requirementType,
bytes memory requirementData
) external returns (uint256);
Parameters:
name (string): Achievement name
description (string): Achievement description
imageURI (string): URI for achievement image/badge
category (uint8): Category index (0-7)
rarity (Rarity): Rarity level (0-4)
points (uint256): Points awarded upon claiming
scoreBoost (uint256): Score boost percentage (basis points)
requirementType (RequirementType): Type of requirement verification
requirementData (bytes): Encoded requirement data
Returns:
uint256: The newly created achievement ID
Gas Estimate: ~200,000 gas
Requirements:
- Caller must have
CREATOR_ROLE
- Name cannot be empty
- Points must be > 0
- Category must be valid (0-7)
Events Emitted:
AchievementCreated(uint256 indexed achievementId, string name, uint8 category, Rarity rarity)
Example Usage:
const { ethers } = require('ethers');
async function createAchievement() {
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
const signer = provider.getSigner();
const contract = new ethers.Contract(
'0x3456789012345678901234567890123456789012',
ACHIEVEMENT_REGISTRY_ABI,
signer
);
// Encode requirement data for score threshold
const requirementData = ethers.utils.defaultAbiCoder.encode(
['uint256'],
[500] // Minimum score of 500
);
const tx = await contract.createAchievement(
'DeFi Explorer',
'Use 5 different DeFi protocols',
'ipfs://QmXyz.../defi-explorer.png',
0, // DeFi category
1, // UNCOMMON rarity
100, // 100 points
200, // 2% score boost (200 basis points)
1, // SCORE_THRESHOLD requirement type
requirementData
);
const receipt = await tx.wait();
const event = receipt.events.find(e => e.event === 'AchievementCreated');
const achievementId = event.args.achievementId;
console.log(`Achievement created with ID: ${achievementId.toString()}`);
return achievementId;
}
updateAchievement
Update an existing achievement’s configuration.
function updateAchievement(
uint256 achievementId,
bytes memory updateData
) external;
Parameters:
achievementId (uint256): ID of achievement to update
updateData (bytes): Encoded update data
Returns: None
Gas Estimate: ~80,000 gas
Requirements:
- Caller must have
CREATOR_ROLE
- Achievement must exist
- Achievement must be active
Events Emitted:
AchievementUpdated(uint256 indexed achievementId, bytes updateData)
deactivateAchievement
Deactivate an achievement (prevent new claims).
function deactivateAchievement(uint256 achievementId) external;
Parameters:
achievementId (uint256): ID of achievement to deactivate
Returns: None
Gas Estimate: ~30,000 gas
Requirements:
- Caller must have
ADMIN_ROLE
- Achievement must exist
Events Emitted:
AchievementDeactivated(uint256 indexed achievementId, uint256 timestamp)
Claiming Functions
claimAchievement
Claim an achievement and receive rewards.
function claimAchievement(
uint256 achievementId,
bytes memory proof
) external;
Parameters:
achievementId (uint256): ID of achievement to claim
proof (bytes): Verification proof (if required)
Returns: None
Gas Estimate: ~180,000 gas (includes badge minting)
Requirements:
- Achievement must be active
- User must not have already claimed
- User must meet requirements
Events Emitted:
AchievementClaimed(address indexed user, uint256 indexed achievementId, uint256 timestamp)
BadgeMinted(address indexed user, uint256 indexed achievementId, uint256 tokenId)
Example Usage:
async function claimAchievement(achievementId) {
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
const signer = provider.getSigner();
const contract = new ethers.Contract(
'0x3456789012345678901234567890123456789012',
ACHIEVEMENT_REGISTRY_ABI,
signer
);
// Generate proof (if needed)
const proof = '0x'; // Empty proof for automatic verification
const tx = await contract.claimAchievement(achievementId, proof);
const receipt = await tx.wait();
// Get claim event
const claimEvent = receipt.events.find(e => e.event === 'AchievementClaimed');
const badgeEvent = receipt.events.find(e => e.event === 'BadgeMinted');
console.log('Achievement claimed!');
console.log('Timestamp:', claimEvent.args.timestamp.toString());
console.log('Badge Token ID:', badgeEvent.args.tokenId.toString());
return receipt;
}
batchClaimAchievements
Claim multiple achievements in a single transaction.
function batchClaimAchievements(
uint256[] calldata achievementIds,
bytes[] calldata proofs
) external returns (uint256[] memory);
Parameters:
achievementIds (uint256[]): Array of achievement IDs to claim
proofs (bytes[]): Array of corresponding proofs
Returns:
uint256[]: Array of minted badge token IDs
Gas Estimate: ~150,000 + (180,000 × number of achievements)
Requirements:
- Arrays must have equal length
- Each achievement must be claimable
Query Functions
getAchievement
Get detailed information about an achievement.
function getAchievement(uint256 achievementId)
external
view
returns (Achievement memory);
Parameters:
achievementId (uint256): ID of achievement to query
Returns:
Achievement: Achievement struct with all details
Gas Estimate: ~5,000 gas (view function)
Example Usage:
async function getAchievement(achievementId) {
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
const contract = new ethers.Contract(
'0x3456789012345678901234567890123456789012',
ACHIEVEMENT_REGISTRY_ABI,
provider
);
const achievement = await contract.getAchievement(achievementId);
console.log('Achievement:', {
id: achievement.id.toString(),
name: achievement.name,
description: achievement.description,
category: achievement.category,
rarity: achievement.rarity,
points: achievement.points.toString(),
totalClaimed: achievement.totalClaimed.toString(),
isActive: achievement.isActive
});
return achievement;
}
getUserAchievements
Get all achievements earned by a user.
function getUserAchievements(address user)
external
view
returns (uint256[] memory);
Parameters:
user (address): User address to query
Returns:
uint256[]: Array of achievement IDs
Gas Estimate: ~3,000 + (1,000 × number of achievements) (view function)
getProgress
Get user’s progress for a specific achievement.
function getProgress(address user, uint256 achievementId)
external
view
returns (Progress memory);
Parameters:
user (address): User address
achievementId (uint256): Achievement ID
Returns:
Progress: Progress struct with current/required/percentage/canClaim
Gas Estimate: ~4,000 gas (view function)
Example Usage:
async function getProgress(userAddress, achievementId) {
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
const contract = new ethers.Contract(
'0x3456789012345678901234567890123456789012',
ACHIEVEMENT_REGISTRY_ABI,
provider
);
const progress = await contract.getProgress(userAddress, achievementId);
console.log('Progress:', {
current: progress.current.toString(),
required: progress.required.toString(),
percentage: progress.percentage.toString(),
lastUpdated: new Date(progress.lastUpdated.toNumber() * 1000).toISOString(),
canClaim: progress.canClaim
});
return progress;
}
getAchievementsByCategory
Get all achievements in a specific category.
function getAchievementsByCategory(uint8 category)
external
view
returns (uint256[] memory);
Parameters:
category (uint8): Category index (0-7)
Returns:
uint256[]: Array of achievement IDs
Gas Estimate: ~3,000 + (500 × number of achievements) (view function)
getAchievementsByRarity
Get all achievements of a specific rarity.
function getAchievementsByRarity(Rarity rarity)
external
view
returns (uint256[] memory);
Parameters:
rarity (Rarity): Rarity level (0-4)
Returns:
uint256[]: Array of achievement IDs
Gas Estimate: ~3,000 + (500 × number of achievements) (view function)
Progress Management Functions
updateProgress
Update progress for a user (verifier only).
function updateProgress(
address user,
uint256 achievementId,
uint256 progressValue
) external;
Parameters:
user (address): User address
achievementId (uint256): Achievement ID
progressValue (uint256): New progress value
Returns: None
Gas Estimate: ~50,000 gas
Requirements:
- Caller must have
VERIFIER_ROLE
- Achievement must exist
- User must not have claimed yet
Events Emitted:
ProgressUpdated(address indexed user, uint256 indexed achievementId, uint256 progress)
batchUpdateProgress
Update progress for multiple users.
function batchUpdateProgress(
address[] calldata users,
uint256[] calldata achievementIds,
uint256[] calldata progressValues
) external;
Parameters:
users (address[]): Array of user addresses
achievementIds (uint256[]): Array of achievement IDs
progressValues (uint256[]): Array of progress values
Returns: None
Gas Estimate: ~40,000 + (50,000 × number of updates)
Requirements:
- All arrays must have equal length
- Caller must have
VERIFIER_ROLE
Badge Functions
getBadge
Get badge information for a claimed achievement.
function getBadge(uint256 tokenId)
external
view
returns (Badge memory);
Parameters:
tokenId (uint256): Badge token ID
Returns:
Badge: Badge struct with achievement ID, owner, claim timestamp
Gas Estimate: ~3,000 gas (view function)
getUserBadges
Get all badges owned by a user.
function getUserBadges(address user)
external
view
returns (uint256[] memory);
Parameters:
user (address): User address
Returns:
uint256[]: Array of badge token IDs
Gas Estimate: ~3,000 + (500 × number of badges) (view function)
Verification Functions
canClaim
Check if a user can claim an achievement.
function canClaim(address user, uint256 achievementId)
external
view
returns (bool);
Parameters:
user (address): User address
achievementId (uint256): Achievement ID
Returns:
bool: True if user can claim, false otherwise
Gas Estimate: ~5,000 gas (view function)
hasClaimed
Check if a user has already claimed an achievement.
function hasClaimed(address user, uint256 achievementId)
external
view
returns (bool);
Parameters:
user (address): User address
achievementId (uint256): Achievement ID
Returns:
bool: True if already claimed, false otherwise
Gas Estimate: ~2,000 gas (view function)
Error Handling
Common Errors
| Error | Description | Solution |
|---|
"Achievement not active" | Achievement is deactivated | Check achievement status |
"Already claimed" | User already claimed | Check hasClaimed() first |
"Requirements not met" | User doesn’t meet requirements | Check progress/requirements |
"Invalid category" | Category index > 7 | Use valid category (0-7) |
"Invalid rarity" | Rarity index > 4 | Use valid rarity (0-4) |
"Achievement not found" | Invalid achievement ID | Verify achievement ID |
Error Handling Examples
async function safeClaimAchievement(achievementId) {
try {
// Check if can claim
const canClaim = await contract.canClaim(userAddress, achievementId);
if (!canClaim) {
throw new Error('Cannot claim achievement yet');
}
// Check if already claimed
const hasClaimed = await contract.hasClaimed(userAddress, achievementId);
if (hasClaimed) {
throw new Error('Achievement already claimed');
}
// Claim achievement
const tx = await contract.claimAchievement(achievementId, '0x');
const receipt = await tx.wait();
return receipt;
} catch (error) {
if (error.message.includes('Requirements not met')) {
console.error('You do not meet the requirements for this achievement');
} else if (error.message.includes('Achievement not active')) {
console.error('This achievement is no longer available');
} else {
console.error('Claim failed:', error.message);
}
throw error;
}
}
Gas Optimization Tips
Batch Operations
// Instead of claiming one by one
for (const id of achievementIds) {
await contract.claimAchievement(id, '0x');
}
// Use batch claim
await contract.batchClaimAchievements(achievementIds, proofs);
Query Optimization
// Query all achievements at once
const achievements = await contract.batchGetAchievements(achievementIds);
// Instead of individual queries
for (const id of achievementIds) {
const achievement = await contract.getAchievement(id);
}