Tracks contributor identity, activity, and reputation scores for paradox discovery and validation.
DISPUTE_ROLEREGISTRY_ADMIN_ROLESCORER_ROLE
ContributorsGovernanceOps / PM
@oz: AccessControl.sol
- Stores a canonical profile per contributor, including reputation, contribution score, validation score, and metadata URI.
- Separates powers via admin, scorer, and dispute roles so that scoring, listing, and arbitration can be delegated cleanly.
- Acts as the on-chain backbone for deciding who can propose, validate, and get rewarded for paradox-related work.
- If scorer or dispute roles are misused, contributor reputation can be distorted and downstream incentives break.
- Any off-chain payout, staking, or governance weight that trusts this registry inherits its errors and biases.
Roles: 3 constants
Events: 6
Functions: 9
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: DISPUTE_ROLE, REGISTRY_ADMIN_ROLE, SCORER_ROLE
- Top functions: adjustReputation, bumpValidationScore, getContributions, getContributor, registerContributor, setActive, setMetaURI, slashOnFalseParadox
- Top events: ContributorMetaUpdated, ContributorRegistered, ContributorScoreUpdated, ContributorSlashed, ContributorStatus, ParadoxSubmitted
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ContributorRegistry is AccessControl {
bytes32 public constant REGISTRY_ADMIN_ROLE = keccak256("REGISTRY_ADMIN_ROLE");
bytes32 public constant SCORER_ROLE = keccak256("SCORER_ROLE");
bytes32 public constant DISPUTE_ROLE = keccak256("DISPUTE_ROLE");
struct Contributor {
bool active;
uint256 reputation;
uint256 contribScore;
uint256 validationScore;
string metaURI;
}
struct ParadoxRef {
uint256 paradoxId; // tokenId din ParadoxToken
bytes32 contentHash; // hash al paradoxului
uint256 timestamp;
}
mapping(address => Contributor) public contributors;
mapping(address => ParadoxRef[]) public contributions;
mapping(uint256 => address) public paradoxAuthor; // paradoxId -> contributor
event ContributorRegistered(address indexed account, string metaURI);
event ContributorStatus(address indexed account, bool active);
event ContributorMetaUpdated(address indexed account, string metaURI);
event ContributorScoreUpdated(address indexed account, string field, uint256 newValue);
event ParadoxSubmitted(address indexed account, uint256 indexed paradoxId, bytes32 contentHash);
event ContributorSlashed(address indexed account, uint256 penalty, string reason);
constructor(address admin) {
require(admin != address(0), "admin=0");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(REGISTRY_ADMIN_ROLE, admin);
_grantRole(SCORER_ROLE, admin);
_grantRole(DISPUTE_ROLE, admin);
}
function registerContributor(address account, string calldata metaURI)
external
onlyRole(REGISTRY_ADMIN_ROLE)
{
require(account != address(0), "account=0");
Contributor storage c = contributors[account];
require(!c.active, "already active");
c.active = true;
c.metaURI = metaURI;
emit ContributorRegistered(account, metaURI);
emit ContributorStatus(account, true);
}
function setActive(address account, bool active)
external
onlyRole(REGISTRY_ADMIN_ROLE)
{
contributors[account].active = active;
emit ContributorStatus(account, active);
}
function setMetaURI(address account, string calldata metaURI)
external
onlyRole(REGISTRY_ADMIN_ROLE)
{
contributors[account].metaURI = metaURI;
emit ContributorMetaUpdated(account, metaURI);
}
/// @notice Leagă un paradox (tokenId + hash) de un contributor.
function submitParadoxRef(
address account,
uint256 paradoxId,
bytes32 contentHash
) external onlyRole(SCORER_ROLE) {
require(contributors[account].active, "not active");
contributions[account].push(
ParadoxRef({
paradoxId: paradoxId,
contentHash: contentHash,
timestamp: block.timestamp
})
);
paradoxAuthor[paradoxId] = account;
contributors[account].contribScore += 1;
emit ParadoxSubmitted(account, paradoxId, contentHash);
emit ContributorScoreUpdated(account, "contribScore", contributors[account].contribScore);
}
/// @notice Adjustare reputație +/- (include slashing).
function adjustReputation(address account, int256 delta)
external
onlyRole(SCORER_ROLE)
{
Contributor storage c = contributors[account];
uint256 old = c.reputation;
if (delta > 0) {
c.reputation = old + uint256(delta);
} else if (delta < 0) {
uint256 absDelta = uint256(-delta);
c.reputation = absDelta >= old ? 0 : old - absDelta;
}
emit ContributorScoreUpdated(account, "reputation", c.reputation);
}
function bumpValidationScore(address account, uint256 delta)
external
onlyRole(SCORER_ROLE)
{
Contributor storage c = contributors[account];
c.validationScore += delta;
emit ContributorScoreUpdated(account, "validationScore", c.validationScore);
}
/// @notice Slashing explicit pentru paradoxuri false (controlat de DAO / Dispute).
function slashOnFalseParadox(address account, uint256 penalty, string calldata reason)
external
onlyRole(DISPUTE_ROLE)
{
Contributor storage c = contributors[account];
uint256 old = c.reputation;
c.reputation = penalty >= old ? 0 : old - penalty;
emit ContributorSlashed(account, penalty, reason);
emit ContributorScoreUpdated(account, "reputation", c.reputation);
}
function getContributor(address account) external view returns (Contributor memory) {
return contributors[account];
}
function getContributions(address account) external view returns (ParadoxRef[] memory) {
return contributions[account];
}
}
Canonical DAO governor wired to the voting token and timelock for parameter and treasury changes.
GovernanceInvestorRisk & Compliance
@oz: Governor.sol@oz: TimelockController.sol@oz: GovernorCountingSimple.sol
- Wraps OpenZeppelin Governor modules into a single contract that controls protocol upgrades and parameter changes.
- Hooks into an ERC20Votes-style token and a TimelockController to enforce voting periods, quorums, and execution delays.
- Defines the proposal lifecycle that every other contract ultimately depends on for configuration changes.
- Misconfigured voting delays, periods, or quorum fractions can make governance either deadlocked or easily captured.
- Any contract wired as a timelock target inherits the security of this governor and its voting token.
Roles: 0 constants
Events: 0
Functions: 10
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: –
- Top functions: _cancel, _execute, _executor, proposalThreshold, propose, quorum, state, supportsInterface
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
import "@openzeppelin/contracts/interfaces/IERC5805.sol";
import "@openzeppelin/contracts/governance/TimelockController.sol";
contract DAOGovernor is
Governor,
GovernorSettings,
GovernorCountingSimple,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorTimelockControl
{
constructor(
string memory name_,
IERC5805 token_, // ERC20Votes (IVotes + IERC6372)
TimelockController timelock_, // Timelock controller
uint256 votingDelay_, // blocks or seconds (depending on clock mode)
uint256 votingPeriod_, // blocks or seconds (depending on clock mode)
uint256 proposalThreshold_, // token units
uint256 quorumFraction_ // percent (e.g. 4 = 4%)
)
Governor(name_)
GovernorSettings(votingDelay_, votingPeriod_, proposalThreshold_)
GovernorVotes(token_)
GovernorVotesQuorumFraction(quorumFraction_)
GovernorTimelockControl(timelock_)
{}
// --- Overrides cerute de Solidity (multiple inheritance) ---
function votingDelay()
public
view
override(IGovernor, GovernorSettings)
returns (uint256)
{
return super.votingDelay();
}
function votingPeriod()
public
view
override(IGovernor, GovernorSettings)
returns (uint256)
{
return super.votingPeriod();
}
function quorum(uint256 timepoint)
public
view
override(IGovernor, GovernorVotesQuorumFraction)
returns (uint256)
{
return super.quorum(timepoint);
}
function state(uint256 proposalId)
public
view
override(Governor, GovernorTimelockControl)
returns (ProposalState)
{
return super.state(proposalId);
}
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
)
public
override(Governor, IGovernor)
returns (uint256)
{
return super.propose(targets, values, calldatas, description);
}
function proposalThreshold()
public
view
override(Governor, GovernorSettings)
returns (uint256)
{
return super.proposalThreshold();
}
function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
)
internal
override(Governor, GovernorTimelockControl)
{
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
)
internal
override(Governor, GovernorTimelockControl)
returns (uint256)
{
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor()
internal
view
override(Governor, GovernorTimelockControl)
returns (address)
{
return super._executor();
}
function supportsInterface(bytes4 interfaceId)
public
view
override(Governor, GovernorTimelockControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
On-chain dispute engine for paradox tokens: freeze, revoke, and record evidence with clear roles.
ARBITRATOR_ROLEGOVERNANCE_ROLE
GovernanceContributorsRisk & Compliance
@oz: AccessControl.sol
- Allows authorized arbitrators to open disputes tied to specific paradox tokens, collect evidence, and decide outcomes.
- Can freeze token metadata and call back into the paradox token to revoke it when a dispute is upheld.
- Keeps a structured audit trail of who opened the dispute, what evidence was submitted, and how it was resolved.
- If arbitrator or governance roles are compromised, valid paradox tokens can be frozen or revoked arbitrarily.
- Poorly defined dispute policies off-chain can turn this contract into a censorship or overreach tool.
Roles: 2 constants
Events: 4
Functions: 7
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: ARBITRATOR_ROLE, GOVERNANCE_ROLE
- Top functions: adjudicate, applyOutcome, fileDispute, freezeMetadata, openDispute, revokeOnDispute, submitEvidence
- Top events: DisputeOpened, DisputeResolved, EvidenceSubmitted, OutcomeApplied
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
interface IParadoxTokenForDisputes {
function revokeOnDispute(uint256 tokenId, string calldata reason) external;
function freezeMetadata(uint256 tokenId) external;
}
contract DisputeResolution is AccessControl {
bytes32 public constant ARBITRATOR_ROLE = keccak256("ARBITRATOR_ROLE");
bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
enum DisputeStatus { None, Open, EvidenceSubmitted, Resolved }
struct Dispute {
uint256 id;
address raisedBy;
uint256 targetTokenId;
string reason;
bytes32 evidenceHash;
string evidenceURI;
DisputeStatus status;
bool upheld;
bool outcomeApplied;
}
IParadoxTokenForDisputes public immutable paradoxToken;
uint256 public nextDisputeId;
mapping(uint256 => Dispute) public disputes;
event DisputeOpened(
uint256 indexed id,
address indexed raisedBy,
uint256 indexed targetTokenId,
string reason
);
event EvidenceSubmitted(uint256 indexed id, bytes32 evidenceHash, string evidenceURI);
event DisputeResolved(uint256 indexed id, bool upheld, string resolutionNote);
event OutcomeApplied(uint256 indexed id, uint256 indexed tokenId, bool upheld);
constructor(address admin, address paradoxToken_) {
require(admin != address(0), "admin=0");
require(paradoxToken_ != address(0), "token=0");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(ARBITRATOR_ROLE, admin);
_grantRole(GOVERNANCE_ROLE, admin);
paradoxToken = IParadoxTokenForDisputes(paradoxToken_);
}
/// @notice Numele cerut explicit în specificație.
function fileDispute(uint256 targetTokenId, string calldata reason)
public
returns (uint256)
{
uint256 id = ++nextDisputeId;
disputes[id] = Dispute({
id: id,
raisedBy: msg.sender,
targetTokenId: targetTokenId,
reason: reason,
evidenceHash: bytes32(0),
evidenceURI: "",
status: DisputeStatus.Open,
upheld: false,
outcomeApplied: false
});
emit DisputeOpened(id, msg.sender, targetTokenId, reason);
return id;
}
/// @notice Alias compatibil cu numele vechi (openDispute -> fileDispute).
function openDispute(uint256 targetTokenId, string calldata reason)
external
returns (uint256)
{
return fileDispute(targetTokenId, reason);
}
/// @notice submitEvidence + hash, aliniat cu standardul de evidență.
function submitEvidence(
uint256 id,
bytes32 evidenceHash,
string calldata evidenceURI
) external {
Dispute storage d = disputes[id];
require(d.status == DisputeStatus.Open, "bad status");
require(
d.raisedBy == msg.sender || hasRole(GOVERNANCE_ROLE, msg.sender),
"not authorized"
);
d.evidenceHash = evidenceHash;
d.evidenceURI = evidenceURI;
d.status = DisputeStatus.EvidenceSubmitted;
emit EvidenceSubmitted(id, evidenceHash, evidenceURI);
}
/// @notice Adjudicare efectuată de arbitru (DAO / comitet).
function adjudicate(
uint256 id,
bool upheld,
string calldata resolutionNote
) external onlyRole(ARBITRATOR_ROLE) {
Dispute storage d = disputes[id];
require(d.status == DisputeStatus.EvidenceSubmitted, "bad status");
d.status = DisputeStatus.Resolved;
d.upheld = upheld;
emit DisputeResolved(id, upheld, resolutionNote);
}
/// @notice Aplică outcome-ul pe ParadoxToken (revoke/freeze).
function applyOutcome(uint256 id) external onlyRole(GOVERNANCE_ROLE) {
Dispute storage d = disputes[id];
require(d.status == DisputeStatus.Resolved, "not resolved");
require(!d.outcomeApplied, "already applied");
d.outcomeApplied = true;
if (d.upheld) {
paradoxToken.revokeOnDispute(d.targetTokenId, d.reason);
} else {
// păstrăm paradoxul dar înghețăm metadata pentru trasabilitate
paradoxToken.freezeMetadata(d.targetTokenId);
}
emit OutcomeApplied(id, d.targetTokenId, d.upheld);
}
}
Anchors document hashes and URIs on-chain so off-chain CSV/JSON paradox data can be verified.
REGISTRAR_ROLE
Infra / DevOpsResearch / DataGovernance
@oz: AccessControl.sol
- Stores a mapping from document IDs to doc hash, URI, timestamp, and registrar address.
- Emits an anchoring event so external systems can watch for new datasets or updated documentation.
- Provides a lightweight, gas-efficient registry that other contracts (like ParadoxNFT) can trust for document integrity.
- If registrar keys are compromised, malicious or incorrect documents can be anchored as if they were valid.
- The registry proves file integrity, not economic soundness—garbage in, garbage out still applies.
Roles: 1 constants
Events: 1
Functions: 2
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: REGISTRAR_ROLE
- Top functions: anchor, get
- Top events: DocAnchored
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Registry pentru hash-uri de documente (CSV/JSON) + event pentru verificare publică.
import "@openzeppelin/contracts/access/AccessControl.sol";
contract DocsHashRegistry is AccessControl {
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
struct DocMeta {
bytes32 docHash; // keccak256(file bytes)
string uri; // ipfs://... sau https://...
uint256 timestamp; // block.timestamp
address registrar; // cine a înregistrat
}
// docId: hash al (uri) sau al (conținutului)
mapping(bytes32 => DocMeta) public docs;
event DocAnchored(bytes32 indexed docId, bytes32 indexed docHash, string uri, address indexed registrar);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(REGISTRAR_ROLE, msg.sender);
}
function anchor(bytes32 docId, bytes32 docHash, string calldata uri) external onlyRole(REGISTRAR_ROLE) {
require(docs[docId].timestamp == 0, "doc exists");
docs[docId] = DocMeta({docHash: docHash, uri: uri, timestamp: block.timestamp, registrar: msg.sender});
emit DocAnchored(docId, docHash, uri, msg.sender);
}
function get(bytes32 docId) external view returns (DocMeta memory) {
return docs[docId];
}
}
First-generation ParadoxVotes implementation with a fixed large initial supply and role-based minting.
MINTER_ROLE
GovernanceInvestor
@oz: AccessControl.sol@oz: ERC20Votes.sol
- Implements an ERC20Votes-compatible token with AccessControl for minting and admin operations.
- Mints a large initial supply on deployment to the admin, representing the early distribution design.
- Useful as a legacy baseline for how voting power was modelled before newer iterations.
- Large initial supply concentrated in a single address can lead to governance capture if not distributed safely.
- If used in production alongside newer tokens, tokenomics and voting power can become confusing.
Roles: 1 constants
Events: 0
Functions: 1
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: MINTER_ROLE
- Top functions: mint
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ParadoxVotes is ERC20Votes, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
constructor(
string memory name_,
string memory symbol_
)
ERC20(name_, symbol_)
ERC20Permit(name_)
{
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
// initial supply: 10 billion tokens
_mint(msg.sender, 10_000_000_000 * 1e18);
}
/// role-based minting
function mint(address to, uint256 amount)
external
onlyRole(MINTER_ROLE)
{
_mint(to, amount);
}
}
Production-grade governance token (ERC20Votes) with pausability and role-based minting.
MINTER_ROLEPAUSER_ROLE
GovernanceInvestorRisk & Compliance
@oz: AccessControl.sol@oz: ERC20.sol@oz: ERC20Pausable.sol
- Extends ERC20Votes with AccessControl roles for minting and pausing transfers in emergency scenarios.
- Supports EIP-2612 permits so signatures can move voting power without on-chain approval transactions.
- Designed to be the main liquid governance or utility token backing the DAO and its voting system.
- Overuse of the pause function can harm liquidity and trust if not governed transparently.
- Minting rights must be tightly controlled; inflation directly dilutes voting power and token value.
Roles: 2 constants
Events: 0
Functions: 8
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: MINTER_ROLE, PAUSER_ROLE
- Top functions: _afterTokenTransfer, _beforeTokenTransfer, _burn, _mint, mint, pause, supportsInterface, unpause
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract GovernanceToken is ERC20, ERC20Pausable, ERC20Permit, ERC20Votes, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor(
address admin,
uint256 initialSupply
)
ERC20("GovernanceToken", "GOV")
ERC20Permit("GovernanceToken")
{
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(MINTER_ROLE, admin);
_grantRole(PAUSER_ROLE, admin);
if (initialSupply > 0) {
_mint(admin, initialSupply);
}
}
// --- public API ---
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
// --- overrides necesare pentru multiple inheritance ---
// Pausable vs ERC20
function _beforeTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20, ERC20Pausable)
{
super._beforeTokenTransfer(from, to, amount);
}
// Votes vs ERC20
function _afterTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._afterTokenTransfer(from, to, amount);
}
function _mint(address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._mint(to, amount);
}
function _burn(address from, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._burn(from, amount);
}
// AccessControl vs ERC20Votes vs ERC20Permit
function supportsInterface(bytes4 interfaceId)
public
view
override(AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Immutable log of index snapshot hashes for verifiable off-chain index exports.
INDEX_PUBLISHER_ROLE
Research / DataGovernanceInfra / DevOps
@oz: AccessControl.sol
- Records the keccak256 hash, timestamp, and version for each published index snapshot.
- Restricts publishing to accounts with an INDEX_PUBLISHER_ROLE to avoid spam or conflicting anchors.
- Lets anyone later recompute the hash of a CSV/JSON export and verify it against the on-chain anchor.
- If publishers upload incorrect hashes or mislabel snapshots, verification will succeed on the wrong data.
- Versioning rules are not enforced economically; operators must follow operational discipline off-chain.
Roles: 1 constants
Events: 1
Functions: 2
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: INDEX_PUBLISHER_ROLE
- Top functions: getAnchor, publishIndex
- Top events: IndexAnchored
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
/// @title IndexHashRegistry
/// @notice Simple on-chain registry for ParadoxNet index snapshots.
/// Stores a keccak256 hash for each index version so that
/// off-chain CSV/JSON exports can be verified on-chain.
contract IndexHashRegistry is AccessControl {
bytes32 public constant INDEX_PUBLISHER_ROLE = keccak256("INDEX_PUBLISHER_ROLE");
struct IndexAnchor {
uint256 version;
uint256 timestamp;
bytes32 snapshotHash;
}
// version => anchor
mapping(uint256 => IndexAnchor) private _anchors;
event IndexAnchored(
uint256 indexed version,
uint256 indexed timestamp,
bytes32 indexed snapshotHash,
address publisher
);
constructor(address admin, address initialPublisher) {
require(admin != address(0), "IndexHashRegistry: admin is zero");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
if (initialPublisher != address(0)) {
_grantRole(INDEX_PUBLISHER_ROLE, initialPublisher);
}
}
/// @notice Publish or update the hash for an index version.
/// @dev Only accounts with INDEX_PUBLISHER_ROLE may call this.
function publishIndex(
uint256 version,
uint256 timestamp,
bytes32 snapshotHash
) external onlyRole(INDEX_PUBLISHER_ROLE) {
require(version != 0, "IndexHashRegistry: version is zero");
require(timestamp != 0, "IndexHashRegistry: timestamp is zero");
require(snapshotHash != bytes32(0), "IndexHashRegistry: hash is zero");
_anchors[version] = IndexAnchor({
version: version,
timestamp: timestamp,
snapshotHash: snapshotHash
});
emit IndexAnchored(version, timestamp, snapshotHash, msg.sender);
}
/// @notice Get the stored anchor for a given version.
function getAnchor(uint256 version) external view returns (IndexAnchor memory) {
return _anchors[version];
}
}
Configurable parameters for each paradox index: weights, scores, and thresholds.
GOVERNANCE_ROLE
GovernanceResearch / Data
@oz: AccessControl.sol
- Stores per-index parameter bundles (weighting, domainScore, threshold, version, updatedAt).
- Limits writes to a GOVERNANCE_ROLE so only governance-approved processes can tune index parameters.
- Acts as the canonical place to read current index weights when pricing or rebalancing products.
- Bad parameter updates can silently skew index behaviour and downstream products without breaking anything on-chain.
- Governance needs off-chain procedures for proposing, simulating, and reviewing parameter changes.
Roles: 1 constants
Events: 1
Functions: 3
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: GOVERNANCE_ROLE
- Top functions: getParams, setParams, setWeights
- Top events: WeightsUpdated
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract IndexParams is AccessControl {
bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
struct Params {
uint256 weighting;
uint256 domainScore;
uint256 threshold;
uint64 version;
uint64 updatedAt;
}
mapping(bytes32 => Params) private _indexParams;
event WeightsUpdated(
bytes32 indexed indexKey,
uint64 version,
uint256 weighting,
uint256 domainScore,
uint256 threshold
);
constructor(address admin) {
require(admin != address(0), "admin=0");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(GOVERNANCE_ROLE, admin);
}
/// @notice Funcția principală: setează/actualizează parametrii indexului.
function setWeights(
bytes32 indexKey,
uint256 weighting,
uint256 domainScore,
uint256 threshold
) public onlyRole(GOVERNANCE_ROLE) {
require(weighting <= 10_000, "Invalid weighting");
require(domainScore <= 10_000, "Invalid domainScore");
Params storage p = _indexParams[indexKey];
p.weighting = weighting;
p.domainScore = domainScore;
p.threshold = threshold;
unchecked {
p.version += 1;
}
p.updatedAt = uint64(block.timestamp);
emit WeightsUpdated(indexKey, p.version, weighting, domainScore, threshold);
}
/// @notice Alias păstrat pentru compatibilitate cu cod/teste vechi.
function setParams(
bytes32 indexKey,
uint256 weighting,
uint256 domainScore,
uint256 threshold
) external {
setWeights(indexKey, weighting, domainScore, threshold);
}
function getParams(bytes32 indexKey) external view returns (Params memory) {
return _indexParams[indexKey];
}
}
Earlier governance token design without on-chain voting snapshots.
MINTER_ROLEPAUSER_ROLE
GovernanceRisk & Compliance
@oz: AccessControl.sol@oz: ERC20.sol@oz: ERC20Pausable.sol
- Implements an ERC20 with pausability and permits but without ERC20Votes voting snapshot logic.
- Keeps AccessControl roles for minting and pausing, mirroring the structure of the newer governance token.
- Intended for migration scenarios or backwards-compatibility with older deployments.
- Because it lacks ERC20Votes, voting power must be computed externally if this token remains in use.
- Running multiple token generations in parallel increases operational and UX complexity.
Roles: 2 constants
Events: 0
Functions: 5
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: MINTER_ROLE, PAUSER_ROLE
- Top functions: _beforeTokenTransfer, mint, pause, supportsInterface, unpause
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/// @title LegacyGovernanceToken
/// @notice ERC20 cu roluri, pausabil și permit (EIP-2612), fără voting snapshots
contract LegacyGovernanceToken is ERC20, ERC20Pausable, ERC20Permit, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor(
string memory name_,
string memory symbol_,
address admin,
uint256 initialSupply
)
ERC20(name_, symbol_)
ERC20Permit(name_)
{
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(MINTER_ROLE, admin);
_grantRole(PAUSER_ROLE, admin);
if (initialSupply > 0) {
_mint(admin, initialSupply);
}
}
// --- public API ---
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
// --- overrides necesare pentru multiple inheritance ---
// Rezolvă conflictul de hook între ERC20 și ERC20Pausable
function _beforeTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20, ERC20Pausable)
{
super._beforeTokenTransfer(from, to, amount);
}
// AccessControl interface resolution
function supportsInterface(bytes4 interfaceId)
public
view
override(AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Test-only docs registry implementing the interface expected by ParadoxNFT.
Protocol Dev
- Provides an in-memory mapping from docId to doc metadata, similar to DocsHashRegistry.
- Implements the minimal docs(...) view function required by ParadoxNFT for unit tests.
- Designed strictly for local development and testing, not for production deployment.
- Deploying this mock on production by mistake would bypass access control and anchoring guarantees.
- Mocks should live in test environments only; treat any mainnet instance as compromised.
Roles: 0 constants
Events: 0
Functions: 2
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: –
- Top functions: docs, setDoc
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @dev Minimal on-chain docs registry used only for tests.
/// Mirrors the IDocsHashRegistry.docs interface expected by ParadoxNFT.
contract MockDocsRegistry {
struct Doc {
bytes32 docHash;
string uri;
uint256 timestamp;
address registrar;
}
mapping(bytes32 => Doc) private _docs;
function setDoc(
bytes32 docId,
bytes32 docHash,
string calldata uri,
uint256 timestamp,
address registrar
) external {
_docs[docId] = Doc({
docHash: docHash,
uri: uri,
timestamp: timestamp,
registrar: registrar
});
}
function docs(bytes32 docId)
external
view
returns (
bytes32 docHash,
string memory uri,
uint256 timestamp,
address registrar
)
{
Doc storage d = _docs[docId];
return (d.docHash, d.uri, d.timestamp, d.registrar);
}
}
Test-only warrants mock exposing a simple canMint(address) view.
Protocol Dev
- Allows tests to toggle whether a given address is allowed to mint paradox NFTs.
- Implements the exact canMint interface expected by the main Warrants or ParadoxNFT contract.
- Useful for simulating different minting policies without touching production logic.
- If wired into production ParadoxNFT deployments, minting constraints collapse to a boolean mapping.
- As with all mocks, it must never be treated as a real entitlement system for value-bearing assets.
Roles: 0 constants
Events: 0
Functions: 2
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: –
- Top functions: canMint, setCanMint
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @dev Minimal warrants mock used only in tests for ParadoxNFT.
/// Exposes the canMint(address) view used by the main contract.
contract MockWarrants {
mapping(address => bool) private _canMint;
function setCanMint(address account, bool value) external {
_canMint[account] = value;
}
function canMint(address account) external view returns (bool) {
return _canMint[account];
}
}
Main ERC-721 for paradoxes, gated by warrants, scores, and document anchors.
MINTER_ROLE
ContributorsGovernanceInvestor
@oz: AccessControl.sol@oz: ERC721URIStorage.sol
- Mints paradox NFTs only when a warrant exists and (optionally) scoring or epoch constraints are satisfied.
- Integrates with DocsHashRegistry to ensure each minted token points to an anchored document hash and URI.
- Tracks epochs, caps, and minimum scores so that paradox minting follows transparent rules.
- Any bug in warrant checks or docs verification can let invalid paradoxes be minted as official assets.
- Economic value quickly concentrates here; thorough audits and simulation are mandatory before mainnet.
Roles: 1 constants
Events: 1
Functions: 8
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: MINTER_ROLE
- Top functions: canMint, docs, mint, setEpoch, setMinScore, setRegistry, setWarrants, supportsInterface
- Top events: Minted
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// ERC-721 pentru paradoxuri: mint condiționat de warrants și (optional) prag de scor.
// Integrează DocsHashRegistry pentru verificare publică.
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
interface IWarrants {
function canMint(address account) external view returns (bool);
}
interface IDocsHashRegistry {
function docs(bytes32 docId) external view returns (
bytes32 docHash,
string memory uri,
uint256 timestamp,
address registrar
);
}
contract ParadoxNFT is ERC721URIStorage, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint256 public totalMinted;
uint256 public currentEpoch;
mapping(uint256 => uint256) public epochCap;
mapping(uint256 => uint256) public epochMinted;
// scor agregat 0..1000
uint256 public minScore;
IWarrants public warrants;
IDocsHashRegistry public registry;
event Minted(
uint256 indexed tokenId,
uint256 indexed epoch,
bytes32 indexed docId,
bytes32 docHash,
uint256 score,
string title,
string status
);
constructor(
string memory name_,
string memory symbol_,
uint256 initialEpoch_,
uint256 initialEpochCap_,
uint256 minScore_,
address warrants_,
address registry_
) ERC721(name_, symbol_) {
require(initialEpochCap_ > 0, "epochCap=0");
require(warrants_ != address(0), "warrants=0");
require(registry_ != address(0), "registry=0");
currentEpoch = initialEpoch_;
epochCap[currentEpoch] = initialEpochCap_;
minScore = minScore_;
warrants = IWarrants(warrants_);
registry = IDocsHashRegistry(registry_);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
}
function setEpoch(uint256 epoch, uint256 cap)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(cap > 0, "cap=0");
currentEpoch = epoch;
epochCap[epoch] = cap;
}
function setMinScore(uint256 newMinScore)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
minScore = newMinScore;
}
function setWarrants(address newWarrants)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(newWarrants != address(0), "warrants=0");
warrants = IWarrants(newWarrants);
}
function setRegistry(address newRegistry)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(newRegistry != address(0), "registry=0");
registry = IDocsHashRegistry(newRegistry);
}
/// tokenURI: deja compus off-chain (IPFS/HTTP), conține titlu/scor/hash/status
function mint(
address to,
string memory tokenURI_,
bytes32 docId,
bytes32 docHashExpected,
uint256 score,
string memory title,
string memory status
)
external
onlyRole(MINTER_ROLE)
returns (uint256 tokenId)
{
require(to != address(0), "to=0");
require(epochCap[currentEpoch] > 0, "epochCap=0");
require(epochMinted[currentEpoch] < epochCap[currentEpoch], "epoch cap");
require(address(warrants) != address(0), "warrants unset");
require(address(registry) != address(0), "registry unset");
require(warrants.canMint(msg.sender), "no warrant");
if (minScore > 0) {
require(score >= minScore, "score<min");
}
// verifică doc în registry
(bytes32 regHash, , uint256 ts, ) = registry.docs(docId);
require(ts != 0, "doc missing");
require(regHash == docHashExpected, "doc hash mismatch");
tokenId = ++totalMinted;
epochMinted[currentEpoch] += 1;
_safeMint(to, tokenId);
_setTokenURI(tokenId, tokenURI_);
emit Minted(tokenId, currentEpoch, docId, regHash, score, title, status);
}
// --- multiple inheritance fix (ERC721URIStorage + AccessControl) ---
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721URIStorage, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Minimal oracle bridge accepting signed off-chain results and emitting on-chain events.
ORACLE_ROLE
Infra / DevOpsResearch / DataGovernance
@oz: AccessControl.sol
- Gives ORACLE_ROLE holders the ability to submit docId/docHash/URI tuples as signed oracle outputs.
- Emits an OracleSubmit event which can be consumed by off-chain listeners or downstream registries.
- Designed to be extendable to full oracle networks (e.g. Chainlink/CCIP) without changing the core flow.
- Oracle key compromise means attackers can publish arbitrary hashes and URIs as if they were valid inputs.
- The contract itself does not verify signatures or economic guarantees; that logic must live around it.
Roles: 1 constants
Events: 1
Functions: 1
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: ORACLE_ROLE
- Top functions: submit
- Top events: OracleSubmit
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Bridge/oracol minimal: acceptă semnături off-chain (AI/service) pentru ancorare.
// În MVP, doar validează un semnatar autorizat. Extensibil la Chainlink/CCIP.
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ParadoxOracleBridge is AccessControl {
bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");
event OracleSubmit(bytes32 indexed docId, bytes32 indexed docHash, string uri, address indexed oracle);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ORACLE_ROLE, msg.sender);
}
function submit(bytes32 docId, bytes32 docHash, string calldata uri) external onlyRole(ORACLE_ROLE) {
emit OracleSubmit(docId, docHash, uri, msg.sender);
// Integrarea cu DocsHashRegistry se face off-chain sau prin orchestrator (script) care ascultă acest eveniment.
}
}
Linear staking pool for an ERC-20 token, used to align contributors and long-term holders.
ContributorsInvestorGovernance
@oz: AccessControl.sol@oz: IERC20.sol
- Lets users stake an ERC-20 token and earn rewards at a configurable tokens-per-second rate.
- Tracks per-user reward accrual and total supply, exposing standard stake, withdraw, and claim functions.
- Uses AccessControl to restrict who can adjust reward rates or other sensitive parameters.
- Incorrect reward rates or update logic can either leak tokens or underpay contributors.
- Staking pools become honeypots; they require careful review of math, time units, and edge cases.
Roles: 0 constants
Events: 3
Functions: 4
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: –
- Top functions: getReward, setRewardRate, stake, withdraw
- Top events: RewardPaid, Staked, Withdrawn
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Staking simplu ERC-20: depui tokenul, acumulezi recompense lineare.
// MVP: fără slashing, fără boost. Ajustează după nevoie.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ParadoxStaking is AccessControl {
IERC20 public immutable stakingToken;
uint256 public rewardRatePerSec; // tokens/sec (setat de admin)
uint256 public lastUpdate;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public balances;
uint256 public totalSupply;
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(address token_) {
require(token_ != address(0), "token=0");
stakingToken = IERC20(token_);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
lastUpdate = block.timestamp;
}
modifier updateReward(address account) {
uint256 elapsed = block.timestamp - lastUpdate;
if (elapsed > 0 && totalSupply > 0) {
rewardPerTokenStored += (elapsed * rewardRatePerSec * 1e18) / totalSupply;
}
lastUpdate = block.timestamp;
if (account != address(0)) {
rewards[account] += ((balances[account] * (rewardPerTokenStored - userRewardPerTokenPaid[account])) / 1e18);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function setRewardRate(uint256 rate) external onlyRole(DEFAULT_ADMIN_ROLE) {
rewardRatePerSec = rate;
}
function stake(uint256 amount) external updateReward(msg.sender) {
require(amount > 0, "amount=0");
stakingToken.transferFrom(msg.sender, address(this), amount);
balances[msg.sender] += amount;
totalSupply += amount;
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount) external updateReward(msg.sender) {
require(amount > 0 && amount <= balances[msg.sender], "invalid");
balances[msg.sender] -= amount;
totalSupply -= amount;
stakingToken.transfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
function getReward() external updateReward(msg.sender) {
uint256 reward = rewards[msg.sender];
rewards[msg.sender] = 0;
require(reward > 0, "no reward");
stakingToken.transfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
Timelock controller ensuring governance decisions respect a minimum delay.
GovernanceRisk & Compliance
@oz: TimelockController.sol
- Wraps OpenZeppelin TimelockController with Paradox-specific deployment parameters.
- Enforces a delay between successful governance votes and actual execution of queued operations.
- Separates proposer, executor, and admin addresses to keep the governance surface small and auditable.
- Misconfigured roles can let a single key both propose and execute changes, bypassing checks and balances.
- Too short a delay reduces the community’s ability to react; too long makes governance feel unresponsive.
Roles: 0 constants
Events: 0
Functions: 0
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: –
- Top functions: –
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/governance/TimelockController.sol";
contract ParadoxTimelock is TimelockController {
constructor(
uint256 minDelay,
address[] memory proposers,
address[] memory executors,
address admin
)
TimelockController(minDelay, proposers, executors, admin)
{}
}
Early ERC-721 implementation for paradox tokens with rich role-based access control.
DISPUTE_RESOLVER_ROLEGRAPH_ROLEMETADATA_ROLEMINTER_ROLEPAUSER_ROLEVALIDATOR_ROLE
ContributorsGovernanceProtocol Dev
@oz: AccessControl.sol@oz: ERC721.sol@oz: ERC721Pausable.sol
- Extends ERC721 with metadata storage, pausability, and roles for minting, metadata updates, and validation.
- Integrates roles for validators, dispute resolvers, and graph updaters to keep token state consistent.
- Intended as a flexible token layer for experimentation before ParadoxNFT hardened the minting pipeline.
- Extra roles and functions expand the attack surface if not governed strictly.
- Running multiple paradox token standards in parallel complicates markets and analytics.
Roles: 6 constants
Events: 5
Functions: 14
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: DISPUTE_RESOLVER_ROLE, GRAPH_ROLE, METADATA_ROLE, MINTER_ROLE, PAUSER_ROLE, VALIDATOR_ROLE
- Top functions: _baseURI, _beforeTokenTransfer, _burn, freezeMetadata, getParadoxMeta, linkGraphNode, mintParadox, pause
- Top events: GraphNodeLinked, MetadataFrozen, ParadoxMinted, ParadoxRevoked, ValidationStatusUpdated
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ParadoxToken is ERC721, ERC721URIStorage, ERC721Pausable, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant METADATA_ROLE = keccak256("METADATA_ROLE");
bytes32 public constant VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE");
bytes32 public constant GRAPH_ROLE = keccak256("GRAPH_ROLE");
bytes32 public constant DISPUTE_RESOLVER_ROLE = keccak256("DISPUTE_RESOLVER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
uint256 private _tokenIdCounter;
string private _baseTokenURI;
/// @notice Statusul de validare pe care îl controlează pipeline-ul + DAO.
enum ValidationStatus {
Unset,
Pending,
Validated,
Rejected,
Revoked
}
/// @notice Metadata minimă on-chain conform specificației.
struct ParadoxMeta {
bytes32 contentHash; // hash al conținutului paradoxului (Keccak/SHA-256)
ValidationStatus status; // starea de validare
bytes32 graphNodeId; // ID în epistemic graph (DKG/Wikibase)
bool frozen; // dacă metadata mai poate fi mutată
}
mapping(uint256 => ParadoxMeta) private _paradoxMeta;
event ParadoxMinted(uint256 indexed tokenId, address indexed to, bytes32 indexed contentHash);
event ValidationStatusUpdated(uint256 indexed tokenId, ValidationStatus status);
event GraphNodeLinked(uint256 indexed tokenId, bytes32 graphNodeId);
event MetadataFrozen(uint256 indexed tokenId);
event ParadoxRevoked(uint256 indexed tokenId, string reason);
constructor(
string memory name_,
string memory symbol_,
address admin_
) ERC721(name_, symbol_) {
require(admin_ != address(0), "admin=0");
_grantRole(DEFAULT_ADMIN_ROLE, admin_);
_grantRole(MINTER_ROLE, admin_);
_grantRole(METADATA_ROLE, admin_);
_grantRole(VALIDATOR_ROLE, admin_);
_grantRole(GRAPH_ROLE, admin_);
_grantRole(DISPUTE_RESOLVER_ROLE, admin_);
_grantRole(PAUSER_ROLE, admin_);
}
// --- config ---
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
function setBaseURI(string calldata newBaseURI) external onlyRole(METADATA_ROLE) {
_baseTokenURI = newBaseURI;
}
// --- funcțiile cheie din specificație ---
/// @notice Mint paradox conform specificației (minimal metadata + hash pointer).
function mintParadox(
address to,
string calldata uri,
bytes32 contentHash
) external onlyRole(MINTER_ROLE) returns (uint256) {
require(to != address(0), "to=0");
require(contentHash != bytes32(0), "hash=0");
uint256 tokenId = ++_tokenIdCounter;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
ParadoxMeta storage meta = _paradoxMeta[tokenId];
meta.contentHash = contentHash;
meta.status = ValidationStatus.Pending;
emit ParadoxMinted(tokenId, to, contentHash);
return tokenId;
}
function setValidationStatus(uint256 tokenId, ValidationStatus status)
external
onlyRole(VALIDATOR_ROLE)
{
require(_exists(tokenId), "nonexistent");
ParadoxMeta storage meta = _paradoxMeta[tokenId];
require(!meta.frozen, "frozen");
meta.status = status;
emit ValidationStatusUpdated(tokenId, status);
}
function linkGraphNode(uint256 tokenId, bytes32 graphNodeId)
external
onlyRole(GRAPH_ROLE)
{
require(_exists(tokenId), "nonexistent");
ParadoxMeta storage meta = _paradoxMeta[tokenId];
require(!meta.frozen, "frozen");
meta.graphNodeId = graphNodeId;
emit GraphNodeLinked(tokenId, graphNodeId);
}
function freezeMetadata(uint256 tokenId)
external
onlyRole(METADATA_ROLE)
{
require(_exists(tokenId), "nonexistent");
ParadoxMeta storage meta = _paradoxMeta[tokenId];
require(!meta.frozen, "already");
meta.frozen = true;
emit MetadataFrozen(tokenId);
}
/// @notice Folosită de DisputeResolution pentru a revoca un paradox disputat.
function revokeOnDispute(uint256 tokenId, string calldata reason)
external
onlyRole(DISPUTE_RESOLVER_ROLE)
{
require(_exists(tokenId), "nonexistent");
ParadoxMeta storage meta = _paradoxMeta[tokenId];
meta.status = ValidationStatus.Revoked;
meta.frozen = true;
emit ParadoxRevoked(tokenId, reason);
emit ValidationStatusUpdated(tokenId, ValidationStatus.Revoked);
emit MetadataFrozen(tokenId);
}
function getParadoxMeta(uint256 tokenId) external view returns (ParadoxMeta memory) {
require(_exists(tokenId), "nonexistent");
return _paradoxMeta[tokenId];
}
// --- pausability ---
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
// --- overrides multiple inheritance ---
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal override(ERC721, ERC721Pausable) {
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}
function _burn(uint256 tokenId)
internal
override(ERC721, ERC721URIStorage)
{
super._burn(tokenId);
delete _paradoxMeta[tokenId];
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721URIStorage, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Refined ParadoxVotes governance token with explicit initialSupply and mint role.
MINTER_ROLE
GovernanceInvestor
@oz: AccessControl.sol@oz: ERC20Votes.sol
- Implements ERC20Votes with AccessControl and configurable initial supply minted to the deployer.
- Separates the MINTER_ROLE from DEFAULT_ADMIN_ROLE so minting can be delegated or later revoked.
- Designed as a clean, auditable base for long-term governance tokenomics.
- As with any governance token, poor distribution or uncontrolled minting leads to vote concentration.
- Token upgrades and migrations must consider how snapshots and voting history are preserved.
Roles: 1 constants
Events: 0
Functions: 4
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: MINTER_ROLE
- Top functions: _afterTokenTransfer, _burn, _mint, mint
- Top events: –
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/// @title ParadoxVotes
/// @notice Governance token with voting power and role-based minting
contract ParadoxVotes is ERC20Votes, AccessControl {
/// @dev Role identifier for accounts allowed to mint new tokens
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
/// @param name_ Token name (e.g. "Paradox Governance")
/// @param symbol_ Token symbol (e.g. "PGOV")
/// @param initialSupply Initial supply minted to deployer (in wei units)
constructor(
string memory name_,
string memory symbol_,
uint256 initialSupply
)
ERC20(name_, symbol_)
ERC20Permit(name_)
{
// Grant deployer admin and minter rights
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
// Mint initial supply to deployer
if (initialSupply > 0) {
_mint(msg.sender, initialSupply);
}
}
/// @notice Mint new tokens to a specified address
/// @dev Only accounts with MINTER_ROLE can call this
/// @param to Recipient address
/// @param amount Amount of tokens to mint (in wei units)
function mint(address to, uint256 amount)
external
onlyRole(MINTER_ROLE)
{
_mint(to, amount);
}
// --- Required overrides for ERC20Votes ---
function _afterTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20Votes)
{
super._afterTokenTransfer(from, to, amount);
}
function _mint(address to, uint256 amount)
internal
override(ERC20Votes)
{
super._mint(to, amount);
}
function _burn(address from, uint256 amount)
internal
override(ERC20Votes)
{
super._burn(from, amount);
}
}
On-chain warrants representing the right to receive governance tokens later (TGE + vesting).
GOVERNANCE_ROLEISSUER_ROLE
ContributorsInvestorGovernance
@oz: AccessControl.sol
- Issues, tracks, and exercises warrant positions that entitle holders to claim governance tokens.
- Supports a simple TGE (token generation event) switch to control when warrants become exercisable.
- Integrates with a token minter interface so exercising a warrant mints real tokens to the beneficiary.
- Incorrect warrant configuration or issuer role abuse can over-mint governance tokens.
- Mis-handled expiries and invalidations can leave dust positions or unfairly locked value.
Roles: 2 constants
Events: 4
Functions: 7
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: GOVERNANCE_ROLE, ISSUER_ROLE
- Top functions: claimOnTGE, configureTGE, exerciseWarrant, grantWarrant, invalidateWarrant, issueWarrant, mint
- Top events: TGEConfigured, WarrantExercised, WarrantGranted, WarrantInvalidated
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
/// @notice Interfață minimă pentru tokenul de governance/utilitate.
interface ITokenMinter {
function mint(address to, uint256 amount) external;
}
contract Warrants is AccessControl {
bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE");
bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
enum WarrantStatus { None, Issued, Exercised, Invalidated }
struct Warrant {
uint256 id;
address beneficiary;
uint256 amount;
uint256 expiry;
WarrantStatus status;
string metaURI;
}
ITokenMinter public immutable token;
mapping(uint256 => Warrant) public warrants;
uint256 public nextWarrantId;
bool public tgeActive;
uint256 public tgeTimestamp;
event WarrantGranted(
uint256 indexed id,
address indexed beneficiary,
uint256 amount,
uint256 expiry,
string metaURI
);
event WarrantExercised(uint256 indexed id, address indexed beneficiary, uint256 amount);
event WarrantInvalidated(uint256 indexed id, string reason);
event TGEConfigured(bool active, uint256 timestamp);
constructor(address admin, address token_) {
require(admin != address(0), "admin=0");
require(token_ != address(0), "token=0");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(ISSUER_ROLE, admin);
_grantRole(GOVERNANCE_ROLE, admin);
token = ITokenMinter(token_);
}
/// @notice grantWarrant conform specificației (issue către investitori).
function grantWarrant(
address beneficiary,
uint256 amount,
uint256 expiry,
string calldata metaURI
) public onlyRole(ISSUER_ROLE) returns (uint256) {
require(beneficiary != address(0), "beneficiary=0");
require(amount > 0, "amount=0");
require(expiry > block.timestamp, "expiry<=now");
uint256 id = ++nextWarrantId;
warrants[id] = Warrant({
id: id,
beneficiary: beneficiary,
amount: amount,
expiry: expiry,
status: WarrantStatus.Issued,
metaURI: metaURI
});
emit WarrantGranted(id, beneficiary, amount, expiry, metaURI);
return id;
}
/// @notice Alias compatibil cu numele vechi (issueWarrant -> grantWarrant).
function issueWarrant(
address beneficiary,
uint256 amount,
uint256 expiry,
string calldata metaURI
) external returns (uint256) {
return grantWarrant(beneficiary, amount, expiry, metaURI);
}
/// @notice Configurare TGE (activare + timestamp de referință).
function configureTGE(bool active, uint256 timestamp)
external
onlyRole(GOVERNANCE_ROLE)
{
if (active) {
require(timestamp <= block.timestamp, "timestamp in future");
}
tgeActive = active;
tgeTimestamp = timestamp;
emit TGEConfigured(active, timestamp);
}
/// @notice claimOnTGE — conversie warrant -> mint tokens după TGE.
function claimOnTGE(uint256 id) public {
Warrant storage w = warrants[id];
require(w.status == WarrantStatus.Issued, "not issuable");
require(tgeActive, "TGE not active");
require(block.timestamp >= tgeTimestamp, "before TGE");
require(block.timestamp <= w.expiry, "expired");
require(msg.sender == w.beneficiary, "not beneficiary");
w.status = WarrantStatus.Exercised;
token.mint(w.beneficiary, w.amount);
emit WarrantExercised(id, w.beneficiary, w.amount);
}
/// @notice Alias compatibil cu fluxul vechi (exerciseWarrant -> claimOnTGE).
function exerciseWarrant(uint256 id) external {
claimOnTGE(id);
}
function invalidateWarrant(uint256 id, string calldata reason)
external
onlyRole(GOVERNANCE_ROLE)
{
Warrant storage w = warrants[id];
require(w.status == WarrantStatus.Issued, "invalid status");
w.status = WarrantStatus.Invalidated;
emit WarrantInvalidated(id, reason);
}
}
ZK-friendly adapter contract for vote and validation proofs with nullifier protection.
PROVER_ROLE
GovernanceResearch / DataInfra / DevOps
@oz: AccessControl.sol
- Provides a PROVER_ROLE-gated entrypoint where off-chain ZK systems can submit verified vote proofs.
- Tracks used nullifiers on-chain to prevent double-voting or replay of the same proof.
- Emits structured events for vote, validation, and attestation proofs to feed analytics and audits.
- If proof systems are weak or compromised, on-chain adapters will happily accept bad attestations.
- Nullifier management must stay consistent with off-chain circuits; mismatches break anonymity guarantees.
Roles: 1 constants
Events: 3
Functions: 3
Deep dive & Solidity source
Key roles · functions · read-only code
Key interfaces
- Roles: PROVER_ROLE
- Top functions: recordAttestation, verifyValidationProof, verifyVoteProof
- Top events: AttestationRecorded, ValidationProofVerified, VoteProofVerified
Solidity source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ZKAdapters is AccessControl {
bytes32 public constant PROVER_ROLE = keccak256("PROVER_ROLE");
mapping(bytes32 => bool) public usedNullifiers;
event VoteProofVerified(
bytes32 indexed proposalId,
address indexed voter,
uint8 support,
uint256 weight,
bytes32 nullifier
);
event ValidationProofVerified(
uint256 indexed paradoxId,
address indexed validator,
bool isValid,
bytes32 nullifier
);
event AttestationRecorded(
bytes32 indexed subject,
bytes32 indexed attestationHash,
address indexed attestor
);
constructor(address admin) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(PROVER_ROLE, admin);
}
function verifyVoteProof(
bytes32 proposalId,
address voter,
uint8 support,
uint256 weight,
bytes32 nullifier,
bytes calldata /* proof */
) external onlyRole(PROVER_ROLE) {
require(!usedNullifiers[nullifier], "nullifier used");
usedNullifiers[nullifier] = true;
emit VoteProofVerified(proposalId, voter, support, weight, nullifier);
}
function verifyValidationProof(
uint256 paradoxId,
address validator,
bool isValid,
bytes32 nullifier,
bytes calldata /* proof */
) external onlyRole(PROVER_ROLE) {
require(!usedNullifiers[nullifier], "nullifier used");
usedNullifiers[nullifier] = true;
emit ValidationProofVerified(paradoxId, validator, isValid, nullifier);
}
function recordAttestation(
bytes32 subject,
bytes32 attestationHash
) external onlyRole(PROVER_ROLE) {
emit AttestationRecorded(subject, attestationHash, msg.sender);
}
}