pragma solidity ^0.5.0; import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v2.5.0/contracts/token/ERC20/ERC20.sol"; import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v2.5.0/contracts/math/SafeMath.sol"; import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v2.5.0/contracts/ownership/Ownable.sol"; import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v2.5.0/contracts/token/ERC20/ERC20Detailed.sol"; contract FreeParking is ERC20, Ownable, ERC20Detailed { constructor( address _owner, uint256 _supply ) ERC20Detailed( "Free Parking Protocol", "PARK", 18 ) public { _mint(_owner, _supply); } using SafeMath for uint256; /** * @notice We require to know who are all the stakeholders. */ address[] internal stakeholders; /** * @notice The accumulated revenue for each stakeholder. */ mapping(address => uint256) internal revenues; /** * @notice The funds in this contract that haven't been * distributed yet. */ uint256 internal accumulated; /** * @notice Method to receive Ether in this contract. *Simply point transfers to the contract address, no function call needed. * This gets distributed later. */ function () external payable { accumulated += msg.value; } // ---------- STAKEHOLDERS ---------- /** * @notice A method to check if an address is a stakeholder. * @param _address The address to verify. * @return bool, uint256 Whether the address is a stakeholder, * and if so its position in the stakeholders array. */ function isStakeholder(address _address) public view returns(bool, uint256) { for (uint256 s = 0; s < stakeholders.length; s += 1){ if (_address == stakeholders[s]) return (true, s); } return (false, 0); } /** * @notice A method to add a stakeholder. * @param _stakeholder The stakeholder to add. */ function addStakeholder(address _stakeholder) public onlyOwner { (bool _isStakeholder, ) = isStakeholder(_stakeholder); if (!_isStakeholder) stakeholders.push(_stakeholder); } /** * @notice A method to remove a stakeholder. * @param _stakeholder The stakeholder to remove. */ function removeStakeholder(address _stakeholder) public onlyOwner { (bool _isStakeholder, uint256 s) = isStakeholder(_stakeholder); if (_isStakeholder){ stakeholders[s] = stakeholders[stakeholders.length - 1]; stakeholders.pop(); } } /** * @notice A simple method that calculates the proportional * share for each stakeholder. * @param _stakeholder The stakeholder to calculate share for. */ function getShare(address _stakeholder) public view returns(uint256) { return balanceOf(_stakeholder) / totalSupply(); } // ---------- REVENUE ---------- /** * @notice A method to distribute revenues to all stakeholders. */ function distribute() public onlyOwner { for (uint256 s = 0; s < stakeholders.length; s += 1){ address stakeholder = stakeholders[s]; uint256 revenue = address(this).balance * getShare(stakeholder); accumulated = accumulated.sub(revenue); revenues[stakeholder] = revenues[stakeholder].add(revenue); } } /** * @notice A method to withdraw revenues. */ function withdraw() public { uint256 revenue = revenues[msg.sender]; revenues[msg.sender] = 0; address(msg.sender).transfer(revenue); } }
0.5.0