EVM Validator Contract
Source on GitHub: github.com/Dobprotocol —
DOBVALIDATOR/distribution-contracts/contracts/DOBValidator.sol
DOBValidator.sol is the on-chain component of the DobValidator platform. It stores submission hashes and TRUFA scores on EVM chains, providing a permanent, tamper-proof record of asset verification results that anyone can query.
Contract Overview
| Property | Value |
|---|---|
| Contract | DOBValidator.sol |
| Solidity | ^0.8.20 |
| Access Control | OpenZeppelin AccessControl |
| Key Role | VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE") |
| Networks | Sepolia, Polygon Amoy, Base Sepolia, Base Mainnet |
Access Control
bytes32 public constant VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE");
| Role | Permissions |
|---|---|
DEFAULT_ADMIN_ROLE | Grant / revoke roles. |
VALIDATOR_ROLE | addProject, setProjectApproved. |
The constructor grants both roles to the admin address passed in.
TrufaScores Struct
struct TrufaScores {
uint32 technicalFeasibility;
uint32 regulatoryCompliance;
uint32 financialViability;
uint32 environmentImpact; // note: environmentImpact, not environmental
uint32 overallTrufaScore;
}
Each field is uint32, validated to be <= 100 on-chain. The five fields pack into a single 32-byte storage slot.
Project Struct
struct Project {
bool exists;
bool approved;
address addedBy; // VALIDATOR_ROLE that called addProject
address approvedBy; // VALIDATOR_ROLE that called setProjectApproved
TrufaScores scores;
uint256 addedAt; // block.timestamp on addProject
uint256 approvedAt; // block.timestamp on setProjectApproved (0 until approved)
}
mapping(bytes32 => Project) public projects;
Core Functions
addProject
function addProject(bytes32 projectHash) external onlyRole(VALIDATOR_ROLE);
Registers projectHash as a Pending project. Reverts if the hash already exists. Emits:
event ProjectAdded(bytes32 indexed projectHash, address indexed addedBy, uint256 timestamp);
setProjectApproved
function setProjectApproved(bytes32 projectHash, TrufaScores calldata scores) external onlyRole(VALIDATOR_ROLE);
Approves a previously added project and writes its TRUFA scores. Reverts if any score is > 100, the project does not exist, or it is already approved. Emits:
event ProjectApproved(
bytes32 indexed projectHash,
address indexed approvedBy,
uint32 technicalFeasibility,
uint32 regulatoryCompliance,
uint32 financialViability,
uint32 environmentImpact,
uint32 overallTrufaScore,
uint256 timestamp
);
getProject / isProjectApproved
function getProject(bytes32 projectHash) external view returns (Project memory);
function isProjectApproved(bytes32 projectHash) external view returns (bool);
getProject reverts if the project hash has never been added.
Two-Step Attestation
The deliberate split lets the validator timestamp a submission as soon as it enters review, then publish scores once the review is complete.
Validator: addProject(0xa635...)
--> Project { exists: true, approved: false, addedBy: msg.sender, addedAt: now }
Validator: setProjectApproved(0xa635..., {95, 92, 85, 88, 90})
--> Project { ..., approved: true, approvedBy: msg.sender, scores: {...}, approvedAt: now }
On-Chain Verification (JS)
import { ethers } from 'ethers';
const contract = new ethers.Contract(validatorAddress, abi, provider);
const project = await contract.getProject(certificateHash);
if (project.exists && project.approved) {
const s = project.scores;
console.log('Technical feasibility:', s.technicalFeasibility);
console.log('Regulatory compliance:', s.regulatoryCompliance);
console.log('Financial viability:', s.financialViability);
console.log('Environment impact:', s.environmentImpact);
console.log('Overall TRUFA:', s.overallTrufaScore);
}
Gas Costs
| Function | Approximate gas |
|---|---|
addProject | ~50k (one new storage slot) |
setProjectApproved | ~60k (overwrites the packed scores slot) |
getProject | view, free off-chain |
Deployed Addresses
TODO: verify and fill in. Addresses are deployed via
DOBVALIDATOR/distribution-contracts/scripts/deploy.tsper network.
| Network | Chain ID | Address |
|---|---|---|
| Ethereum Sepolia | 11155111 | TODO |
| Polygon Amoy | 80002 | TODO |
| Base Sepolia | 84532 | TODO |
| Base Mainnet | 8453 | TODO |