Contract Name:
StatValidation
Contract Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "../interfaces/ICollectionRegistry.sol";
/// @title StatValidation
/// @notice Library for validating stat ranges and class-specific requirements
library StatValidation {
// ------------------------- Constants -------------------------
uint64 private constant MIN_STAT_VALUE = 50;
uint64 private constant MAX_STAT_VALUE = 200;
uint64 private constant MAX_STAT_INCREASE = 50;
uint8 private constant MAX_COMPLEXITY = 3;
// Gas limits by complexity tier
uint256 private constant TIER1_GAS_LIMIT = 30000;
uint256 private constant TIER2_GAS_LIMIT = 50000;
uint256 private constant TIER3_GAS_LIMIT = 80000;
// ------------------------- Errors -------------------------
error InvalidStatRange(uint64 value, uint64 min, uint64 max);
error InvalidStatIncrease(
uint64 oldValue,
uint64 newValue,
uint64 maxIncrease
);
error InvalidClassStats(uint8 classType, string reason);
error InvalidComplexity(uint8 complexity, uint256 gasUsed);
// ------------------------- Core validation -------------------------
/// @notice Validate a stat value is within acceptable range
/// @param value Stat value to check
/// @param min Minimum allowed value
/// @param max Maximum allowed value
function validateStatRange(
uint64 value,
uint64 min,
uint64 max
) public pure {
if (value < min || value > max) {
revert InvalidStatRange(value, min, max);
}
}
/// @notice Validate a stat increase is within acceptable range
/// @param oldValue Previous stat value
/// @param newValue New stat value
/// @param maxIncrease Maximum allowed increase
function validateStatIncrease(
uint64 oldValue,
uint64 newValue,
uint64 maxIncrease
) public pure {
if (newValue < oldValue || newValue > oldValue + maxIncrease) {
revert InvalidStatIncrease(oldValue, newValue, maxIncrease);
}
}
// ------------------------- Class validation -------------------------
/// @notice Validate stats are appropriate for class type
/// @param classType The class archetype
/// @param stats Array of stats [vitality, strength, agility, defense]
function validateClassStats(
uint8 classType,
uint64[4] memory stats
) public pure {
ICollectionRegistry.ClassArchetype archetype = ICollectionRegistry
.ClassArchetype(classType);
// Validate base requirements for each class
if (archetype == ICollectionRegistry.ClassArchetype.WARRIOR) {
if (stats[1] < 80 || stats[3] < 80) {
// strength and defense
revert InvalidClassStats(
classType,
"Warrior requires high strength and defense"
);
}
} else if (archetype == ICollectionRegistry.ClassArchetype.ROGUE) {
if (stats[2] < 80) {
// agility
revert InvalidClassStats(
classType,
"Rogue requires high agility"
);
}
} else if (archetype == ICollectionRegistry.ClassArchetype.PALADIN) {
if (stats[0] < 80 || stats[3] < 70) {
// vitality and defense
revert InvalidClassStats(
classType,
"Paladin requires high vitality and defense"
);
}
} else if (archetype == ICollectionRegistry.ClassArchetype.BERSERKER) {
if (stats[1] < 90) {
// strength
revert InvalidClassStats(
classType,
"Berserker requires very high strength"
);
}
}
// Validate all stats are within global range
for (uint256 i = 0; i < 4; i++) {
validateStatRange(stats[i], MIN_STAT_VALUE, MAX_STAT_VALUE);
}
}
// ------------------------- Complexity validation -------------------------
/// @notice Validate gas usage against complexity tier
/// @param complexity Complexity tier (1-3)
/// @param gasUsed Amount of gas used
function validateComplexityRequirements(
uint8 complexity,
uint256 gasUsed
) public pure {
if (complexity == 0 || complexity > MAX_COMPLEXITY) {
revert InvalidComplexity(complexity, gasUsed);
}
uint256 gasLimit = complexity == 1
? TIER1_GAS_LIMIT
: complexity == 2
? TIER2_GAS_LIMIT
: TIER3_GAS_LIMIT;
if (gasUsed > gasLimit) {
revert InvalidComplexity(complexity, gasUsed);
}
}
// ------------------------- Utility functions -------------------------
/// @notice Get the gas limit for a complexity tier
/// @param complexity Complexity tier (1-3)
/// @return uint256 Gas limit for the tier
function getGasLimitForComplexity(
uint8 complexity
) public pure returns (uint256) {
return
complexity == 1
? TIER1_GAS_LIMIT
: complexity == 2
? TIER2_GAS_LIMIT
: complexity == 3
? TIER3_GAS_LIMIT
: 0;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @title ICollectionRegistry
/// @notice Interface for managing whitelisted NFT collections and their base stats
interface ICollectionRegistry {
// ------------------------- Type definitions -------------------------
/// @notice Enum for different class archetypes
enum ClassArchetype {
WARRIOR, // High strength/defense
ROGUE, // High agility/critical
PALADIN, // Balanced with healing
BERSERKER // High damage/risk
}
/// @notice Stats structure for NFT collections
struct CollectionStats {
uint64 baseVitality;
uint64 baseStrength;
uint64 baseAgility;
uint64 baseDefense;
uint8 classType; // ClassArchetype
uint8 complexity; // For gas limit determination
bool isWhitelisted;
}
// ------------------------- Events -------------------------
/// @notice Event emitted when a collection is whitelisted
event CollectionWhitelisted(
address indexed collection,
uint64 baseVitality,
uint64 baseStrength,
uint64 baseAgility,
uint64 baseDefense,
ClassArchetype classType,
uint8 complexity
);
/// @notice Event emitted when a collection's stats are updated
event CollectionStatsUpdated(
address indexed collection,
uint64 baseVitality,
uint64 baseStrength,
uint64 baseAgility,
uint64 baseDefense,
ClassArchetype classType,
uint8 complexity
);
/// @notice Event emitted when a collection is removed from whitelist
event CollectionRemoved(address indexed collection);
// ------------------------- Admin functions -------------------------
/// @notice Whitelist a new NFT collection with base stats
/// @param collection Address of the NFT collection
/// @param baseVitality Initial vitality for NFTs from this collection
/// @param baseStrength Initial strength for NFTs from this collection
/// @param baseAgility Initial agility for NFTs from this collection
/// @param baseDefense Initial defense for NFTs from this collection
/// @param classType Class archetype for this collection
/// @param complexity Gas complexity tier (1-3)
function whitelistCollection(
address collection,
uint64 baseVitality,
uint64 baseStrength,
uint64 baseAgility,
uint64 baseDefense,
ClassArchetype classType,
uint8 complexity
) external;
/// @notice Update base stats for a whitelisted collection
/// @param collection Address of the NFT collection
/// @param baseVitality New base vitality
/// @param baseStrength New base strength
/// @param baseAgility New base agility
/// @param baseDefense New base defense
/// @param classType New class archetype
/// @param complexity New complexity tier
function updateCollectionStats(
address collection,
uint64 baseVitality,
uint64 baseStrength,
uint64 baseAgility,
uint64 baseDefense,
ClassArchetype classType,
uint8 complexity
) external;
/// @notice Remove a collection from the whitelist
/// @param collection Address of the NFT collection to remove
function removeCollection(address collection) external;
// ------------------------- View functions -------------------------
/// @notice Check if a collection is whitelisted
/// @param collection Address of the NFT collection to check
/// @return bool True if collection is whitelisted
function isWhitelisted(address collection) external view returns (bool);
/// @notice Get base stats for a collection
/// @param collection Address of the NFT collection
/// @return CollectionStats struct containing base stats
function getCollectionStats(
address collection
) external view returns (CollectionStats memory);
}