QualityAssessment
QualityAssessment.sol is the on-chain oracle contract that records quality scores for RWA certificates. It supports two modes: a legacy 4-dimension model and a configurable N-dimension profile model. The profile model is used in production; the legacy model remains for backwards compatibility.
Source: contracts/oracle/QualityAssessment.sol.
Roles
| Role | keccak256 constant | Who holds it | What it allows |
|---|---|---|---|
ADMIN_ROLE | keccak256("ADMIN_ROLE") | Oracle admin | Configure profiles, rating bands, set methodology scores |
ORACLE_ROLE | keccak256("ORACLE_ROLE") | Oracle service account | assessQuality, assessQualityFlexible |
ROLE_MANAGER | keccak256("ROLE_MANAGER") | Admin | Grant/revoke ORACLE_ROLE |
Assessment Modes
Legacy 4-Dimension Model (assessQuality)
Four fixed dimensions, each capped at 25 points (total max = 100):
| Dimension | Max score | Description |
|---|---|---|
vintageScore | 25 | Age of the credit — newer is higher |
methodologyScore | 25 | Verification standard used (VCS = 20, GS = 23, etc.) |
additionalityScore | 25 | Whether the benefit would have occurred without the project |
coBenefitsScore | 25 | SDGs, social impact, co-benefits |
function assessQuality(
string memory _certificateSerial,
AssetType _assetType,
uint8 _vintageScore,
uint8 _methodologyScore,
uint8 _additionalityScore,
uint8 _coBenefitsScore
) external onlyRole(ORACLE_ROLE)
Result stored in qualityMetrics[serial]. Emits QualityAssessed and QualityMetricsUpdated.
Configurable N-Dimension Model (assessQualityFlexible)
Dimensions are configured per asset type by ADMIN_ROLE using configureQualityProfile. Scores are submitted per-dimension and normalized to 0–100.
function assessQualityFlexible(
string calldata _certificateSerial,
uint8 _assetType,
uint8[] calldata _scores
) external onlyRole(ORACLE_ROLE)
Requirements:
- A quality profile must be configured for
_assetType(profileConfigured[_assetType] == true). _scores.lengthmust equal the configured dimension count.- Each score must not exceed its dimension's
maxScore.
Normalization: normalizedScore = (rawTotal × 100) / maxPossible.
The rating is resolved from the configured rating bands. Result stored in flexibleAssessments[serial]. Emits FlexibleQualityAssessed.
Quality Profiles
A quality profile defines the dimensions used for flexible assessment:
struct QualityDimension {
string name; // e.g. "Technical Quality", "Additionality"
uint8 maxScore; // Maximum points for this dimension
}
Configure a Profile
function configureQualityProfile(
uint8 _assetType,
string[] calldata _names,
uint8[] calldata _maxScores
) external onlyRole(ADMIN_ROLE)
Replaces any existing profile. The maxScores array must sum to the total possible score before normalization. The oracle normalizes the raw total to 0–100.
Production profiles for carbon credits use 6 dimensions with max scores [25, 20, 20, 15, 12, 8] (sum = 100), so normalization is a no-op in practice.
Read a Profile
function getQualityProfile(uint8 _assetType)
external view returns (QualityDimension[] memory)
Rating Bands
Rating bands map normalized score ranges to letter grades:
struct RatingBand {
string label; // e.g. "AAA", "AA", "A", "BBB"
uint8 minScore; // Minimum score for this band (inclusive)
}
Bands must be configured in descending order of minScore (highest rating first). The oracle walks the array and returns the first band where score >= minScore.
Configure Bands
function configureRatingBands(
uint8 _assetType,
string[] calldata _labels,
uint8[] calldata _minScores
) external onlyRole(ADMIN_ROLE)
Default bands (carbon credits)
| Band | Min score |
|---|---|
| AAA | 90 |
| AA | 80 |
| A | 70 |
| BBB | 60 |
| Not Eligible | 0 |
Read Bands
function getRatingBands(uint8 _assetType)
external view returns (RatingBand[] memory)
function getRating(uint8 _assetType, uint8 _score)
external view returns (string memory)
Vintage Score Helper
function calculateVintageScore(uint256 _vintage) public view returns (uint8)
| Credit age | Score |
|---|---|
| 0–2 years | 25 |
| 3–5 years | 20 |
| 6–10 years | 15 |
| 11–15 years | 10 |
| > 15 years | 5 |
The oracle uses this to auto-derive the vintage dimension score rather than asking the registry to provide it.
Default Methodology Scores (Carbon)
Set during initialize. Overridable with setMethodologyScore (ADMIN_ROLE).
| Methodology | Score (0–25) |
|---|---|
| Gold Standard (GS) | 23 |
| Verified Carbon Standard (VCS) | 20 |
| Climate Action Reserve (CAR) | 18 |
| American Carbon Registry (ACR) | 18 |
| Clean Development Mechanism (CDM) | 15 |
Minimum Quality Threshold
function meetsQualityThreshold(string memory _certificateSerial)
external view returns (bool)
Returns true when the certificate's score meets the per-asset-type minimum. If no minimum is configured for an asset type, DEFAULT_MIN_QUALITY_SCORE = 60 applies.
Default minimums set in initialize:
| Asset type | Min score |
|---|---|
| Carbon, Plastic | 60 |
| Nitrogen, Phosphorus, Water | 55 |
| Agricultural Land | 50 |
Key View Functions
| Function | Returns |
|---|---|
getQualityMetrics(serial) | Legacy QualityMetrics struct |
getFlexibleAssessment(serial) | FlexibleAssessment struct (flexible mode) |
getDimensionScores(serial, assetType) | Per-dimension scores as uint8[] |
getQualityScore(serial) | totalScore from legacy metrics |
getRating(assetType, score) | Rating band label for a given score |
getQualityProfile(assetType) | Configured dimension array |
getRatingBands(assetType) | Configured band array |
meetsQualityThreshold(serial) | Whether score ≥ minimum for its asset type |
calculateVintageScore(vintage) | Legacy vintage helper |
Events
| Event | When emitted |
|---|---|
QualityAssessed(serial, assetType, totalScore, assessor) | assessQuality |
QualityMetricsUpdated(serial, assetType, v, m, a, c) | assessQuality |
FlexibleQualityAssessed(serial, assetType, totalScore, rating, assessor) | assessQualityFlexible |
QualityProfileConfigured(assetType, dimensionCount) | configureQualityProfile |
RatingBandsConfigured(assetType, bandCount) | configureRatingBands |
MethodologyScoreSet(assetType, methodology, score) | setMethodologyScore |
MinQualityScoreSet(assetType, minScore) | setMinQualityScore |
Custom Errors
| Error | Condition |
|---|---|
ProfileNotConfigured(assetType) | assessQualityFlexible called before profile is configured |
DimensionCountMismatch(expected, provided) | _scores.length does not match configured dimensions |
ScoreExceedsMax(dimIndex, score, maxScore) | A dimension score exceeds its maxScore |
EmptyDimensions | configureQualityProfile called with zero dimensions |
EmptyBands | configureRatingBands called with zero bands |
BandsNotDescending | Bands not in descending minScore order |
NoBandsConfigured(assetType) | Rating lookup on unconfigured asset type |
UUPS Upgrade
_authorizeUpgrade requires ADMIN_ROLE. A 30-slot storage gap (uint256[30] private __gap) is reserved for future upgrades.