| |
| pragma solidity ^0.8.0; |
|
|
| contract PureConvo { |
| |
| |
| string public constant name = "PureConvo Research Registry"; |
| string public constant symbol = "CONVO"; |
|
|
| |
| struct Researcher { |
| bool isRegistered; |
| uint256 reputationScore; |
| string role; |
| } |
| |
| mapping(address => Researcher) public researchers; |
| address public labAdmin; |
|
|
| |
| struct DialectEntry { |
| uint256 id; |
| string phrase; |
| string dialect; |
| string ipfsCid; |
| address contributor; |
| string licenseType; |
| uint256 verificationCount; |
| bool isVerified; |
| } |
|
|
| uint256 public entryCounter; |
| mapping(uint256 => DialectEntry) public entries; |
|
|
| |
| struct DataSnapshot { |
| uint256 timestamp; |
| string dataType; |
| string ipfsCid; |
| string description; |
| address uploader; |
| } |
|
|
| mapping(string => DataSnapshot[]) public backups; |
|
|
| |
| event EntryProposed(uint256 indexed id, string phrase, address indexed proposer); |
| event EntryVerified(uint256 indexed id, address indexed verifier); |
| event ReputationMinted(address indexed researcher, uint256 amount); |
| event BackupCreated(string indexed dataKey, string ipfsCid, uint256 timestamp); |
|
|
| constructor() { |
| labAdmin = msg.sender; |
| researchers[msg.sender] = Researcher(true, 100, "Admin"); |
| } |
|
|
| |
| modifier onlyAdmin() { |
| require(msg.sender == labAdmin, "Only Lab Admin can do this"); |
| _; |
| } |
|
|
| modifier onlyRegistered() { |
| require(researchers[msg.sender].isRegistered, "Must be registered researcher"); |
| _; |
| } |
|
|
| |
|
|
| function registerResearcher(address _user, string memory _role) public onlyAdmin { |
| researchers[_user] = Researcher(true, 10, _role); |
| } |
|
|
| function proposeEntry(string memory _phrase, string memory _dialect, string memory _ipfsCid, string memory _license) public onlyRegistered { |
| entryCounter++; |
| |
| entries[entryCounter] = DialectEntry(entryCounter, _phrase, _dialect, _ipfsCid, msg.sender, _license, 0, false); |
| emit EntryProposed(entryCounter, _phrase, msg.sender); |
| } |
|
|
| function verifyEntry(uint256 _id) public onlyRegistered { |
| require(entries[_id].contributor != msg.sender, "Cannot verify own entry"); |
| require(!entries[_id].isVerified, "Already verified"); |
|
|
| entries[_id].verificationCount++; |
|
|
| |
| if (entries[_id].verificationCount >= 2) { |
| entries[_id].isVerified = true; |
| _mintReputation(entries[_id].contributor, 50); |
| emit EntryVerified(_id, msg.sender); |
| } |
| |
| |
| _mintReputation(msg.sender, 10); |
| } |
|
|
| function createBackup(string memory _dataKey, string memory _dataType, string memory _ipfsCid, string memory _description) public onlyRegistered { |
| DataSnapshot memory newSnap = DataSnapshot(block.timestamp, _dataType, _ipfsCid, _description, msg.sender); |
| backups[_dataKey].push(newSnap); |
| emit BackupCreated(_dataKey, _ipfsCid, block.timestamp); |
| } |
|
|
| |
| |
| |
| function getLatestBackup(string memory _dataKey) public view returns (string memory ipfsCid, uint256 timestamp) { |
| require(backups[_dataKey].length > 0, "No backups found"); |
| DataSnapshot memory snap = backups[_dataKey][backups[_dataKey].length - 1]; |
| return (snap.ipfsCid, snap.timestamp); |
| } |
|
|
| |
| function getLicenseInfo(uint256 _id) public view returns (string memory license, address contributor) { |
| return (entries[_id].licenseType, entries[_id].contributor); |
| } |
|
|
| |
| function _mintReputation(address _user, uint256 _amount) internal { |
| researchers[_user].reputationScore += _amount; |
| emit ReputationMinted(_user, _amount); |
| } |
| } |
|
|