UsageContract.sol
1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.0; 3 4 contract UsageContract { 5 mapping(address => bool) private developers; 6 address[] private developerList; 7 mapping(address => bool) private clients; 8 mapping(address => uint256) public clientFunding; 9 mapping(address => uint256) private developerBalances; 10 11 // Voting system for developer registration 12 mapping(address => bool) private pendingRegistrations; 13 mapping(address => mapping(address => bool)) private votes; 14 mapping(address => mapping(address => bool)) private hasVoted; 15 mapping(address => uint256) private voteCount; 16 17 event DeveloperRegistered(address indexed developer); 18 event ClientRegistered(address indexed client); 19 event Funded(address indexed client, uint256 amount); 20 event Consumed(address indexed client, uint256 amount); 21 22 constructor() { 23 developers[msg.sender] = true; 24 developerList.push(msg.sender); 25 emit DeveloperRegistered(msg.sender); 26 } 27 28 function requestDeveloperRegistration() external { 29 require(!developers[msg.sender], "Already registered as developer"); 30 require(!pendingRegistrations[msg.sender], "Registration already pending"); 31 32 pendingRegistrations[msg.sender] = true; 33 // Do not add to developerList or emit event yet - wait for voting 34 } 35 36 function hasPendingRegistrationRequest(address developer) external view returns (bool) { 37 return pendingRegistrations[developer]; 38 } 39 40 function voteForDeveloper(address developer, bool approve) external { 41 require(developers[msg.sender], "Only developers can vote"); 42 require(pendingRegistrations[developer], "No pending registration for this developer"); 43 require(!hasVoted[developer][msg.sender], "Already voted for this developer"); 44 45 votes[developer][msg.sender] = approve; 46 hasVoted[developer][msg.sender] = true; 47 voteCount[developer]++; 48 49 // Check if all developers have voted 50 if (voteCount[developer] == developerList.length) { 51 _finalizeVoting(developer); 52 } 53 } 54 55 function _finalizeVoting(address developer) private { 56 uint256 approvalCount = 0; 57 58 // Count approval votes 59 for (uint256 i = 0; i < developerList.length; i++) { 60 if (votes[developer][developerList[i]]) { 61 approvalCount++; 62 } 63 } 64 65 // Require majority (>50%) approval 66 bool approved = approvalCount * 2 > developerList.length; 67 68 if (approved) { 69 developers[developer] = true; 70 developerList.push(developer); 71 emit DeveloperRegistered(developer); 72 } 73 74 // Clean up voting data 75 pendingRegistrations[developer] = false; 76 voteCount[developer] = 0; 77 for (uint256 i = 0; i < developerList.length; i++) { 78 delete votes[developer][developerList[i]]; 79 delete hasVoted[developer][developerList[i]]; 80 } 81 } 82 83 function registerClient() external { 84 clients[msg.sender] = true; 85 emit ClientRegistered(msg.sender); 86 } 87 88 function isDeveloper() external view returns (bool) { 89 return developers[msg.sender]; 90 } 91 92 function isClient(address user) external view returns (bool) { 93 return clients[user]; 94 } 95 96 function fund() external payable { 97 require(msg.value > 0, "No funds sent"); 98 clients[msg.sender] = true; 99 clientFunding[msg.sender] += msg.value; 100 emit Funded(msg.sender, msg.value); 101 } 102 103 function getClientFunding() external view returns (uint256) { 104 return clientFunding[msg.sender]; 105 } 106 107 function requestPayout() external { 108 require(clients[msg.sender], "Only clients can request payout"); 109 require(clientFunding[msg.sender] > 0, "No funds available for payout"); 110 111 uint256 amount = clientFunding[msg.sender]; 112 113 (bool sent, ) = msg.sender.call{value: amount}(""); 114 require(sent, "Failed to send payout"); 115 116 clientFunding[msg.sender] = 0; 117 } 118 119 function consume(uint256 amount) external returns (uint256) { 120 emit Consumed(msg.sender, clientFunding[msg.sender]); 121 require( 122 clientFunding[msg.sender] >= amount, 123 "Insufficient client funding" 124 ); 125 require(developerList.length > 0, "No developers registered"); 126 clientFunding[msg.sender] -= amount; 127 uint256 share = amount / developerList.length; 128 uint256 remainder = amount % developerList.length; 129 for (uint256 i = 0; i < developerList.length; i++) { 130 developerBalances[developerList[i]] += share; 131 } 132 if (remainder > 0) { 133 developerBalances[developerList[0]] += remainder; 134 } 135 return clientFunding[msg.sender]; 136 } 137 138 function getDeveloperBalance() external view returns (uint256) { 139 require(developers[msg.sender], "Only developers can check their balance"); 140 return developerBalances[msg.sender]; 141 } 142 143 function withdrawBalance() external { 144 require(developers[msg.sender], "Only developers can withdraw"); 145 uint256 balance = developerBalances[msg.sender]; 146 require(balance > 0, "No balance to withdraw"); 147 148 developerBalances[msg.sender] = 0; 149 (bool sent, ) = msg.sender.call{value: balance}(""); 150 require(sent, "Failed to withdraw balance"); 151 } 152 }