pragma solidity ^0.4.19; contract Onwable { address owner; function Onwable() public { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner); _; } } contract Reputable is Onwable { uint constant REPUTATION_FEE = 10000 wei; uint constant REPUTATION_REFUND = 10000 wei; struct Product { string name; string domain; uint16 downVotes; uint16 upVotes; uint donatedValue; bool closed; bool exists; } struct Voter { uint refundableBalance; } Product[] public products; Voter[] public voters; uint addingFee; mapping(address => uint) voterIdByAddress; mapping(uint => uint[]) downVoters; // productId => VoterId[] mapping(uint => uint[]) upVoters; // productId => VoterId[] modifier includeAddingFee() { require(msg.value >= REPUTATION_FEE); _; } modifier includeVoteFee() { require(msg.value >= REPUTATION_FEE); _; } modifier productExits(uint _productId) { require(products[_productId].exists); _; } function addProduct(string _name, string _domain) public payable includeAddingFee() { Product memory product = Product({ name: _name, domain: _domain, downVotes: 0, upVotes: 0, donatedValue: 0, closed: false, exists: true }); products.push(product); addingFee += msg.value; } } contract Votable is Reputable { function downVote(uint _productId) public payable productExits(_productId) includeVoteFee() { uint voterId = voterIdByAddress[msg.sender]; if (voterId == 0) { voterId = voters.push(Voter(REPUTATION_REFUND)) - 1; } downVoters[_productId].push(voterId); } function upVote(uint _productId) public payable productExits(_productId) includeVoteFee() { uint voterId = voterIdByAddress[msg.sender]; if (voterId == 0) { voterId = voters.push(Voter(0)) - 1; } upVoters[_productId].push(voterId); Product memory product = products[_productId]; product.donatedValue += REPUTATION_REFUND; products[_productId] = product; } } contract Refundable is Votable { modifier allRefundsSent(uint _productId) { require(msg.value >= _refundCalc(_productId)); _; } modifier voterExists() { require(voterIdByAddress[msg.sender] != 0); _; } function removeProductById(uint _productId) public payable allRefundsSent(_productId) { Product memory product = products[_productId]; product.closed = true; product.donatedValue = _refundCalc(_productId); products[_productId] = product; _refundDownVoters(_productId); } function _refundCalc(uint _productId) private view returns (uint) { Product memory product = products[_productId]; int calcResult = int((_countDownVoters(_productId) * REPUTATION_FEE) - product.donatedValue); if (calcResult <= 0) { return 0; } else { return uint(calcResult); } } function _refundDownVoters(uint _productId) private { for (uint i = 0; i < _getAllDownVoters(_productId).length; i++) { Voter storage voter = voters[i]; voter.refundableBalance += REPUTATION_FEE; } } function _countDownVoters(uint _productId) private view returns (uint) { return downVoters[_productId].length; } function _getAllDownVoters(uint _productId) private view returns (uint[]) { return downVoters[_productId]; } function withdraw() external voterExists() { uint voterId = voterIdByAddress[msg.sender]; Voter memory voter = voters[voterId]; voter.refundableBalance = 0; msg.sender.transfer(voter.refundableBalance); } } contract ReputationHunt is Refundable { string constant NAME = "REPUTATION HUNT"; function onwerWithdraw() external onlyOwner() { msg.sender.transfer(addingFee); } }
0.4.19