|
pragma solidity ^0.4.19; |
|
|
|
contract owned { |
|
address public owner; |
|
|
|
function owned() public { |
|
owner = msg.sender; |
|
} |
|
|
|
modifier onlyOwner { |
|
require(msg.sender == owner); |
|
_; |
|
} |
|
|
|
function transferOwnership(address newOwner) onlyOwner public{ |
|
owner = newOwner; |
|
} |
|
} |
|
|
|
contract tokenRecipient { |
|
|
|
uint256 public profit; |
|
|
|
event receivedEther(address sender, uint amount); |
|
event balanceUpdated(address sender, uint amount, uint balance); |
|
|
|
function () payable public { |
|
receivedEther(msg.sender, msg.value); |
|
|
|
// profit += msg.value; |
|
// balanceUpdated(msg.sender, msg.value, profit); |
|
} |
|
} |
|
|
|
contract Shareholders is owned, tokenRecipient { |
|
// Track total shares in existence |
|
uint totalShares = 100; |
|
// uint availableShares = 50 |
|
uint lastProfitShare = now; |
|
address[] memberList; |
|
uint profitShareInterval = 30 days; |
|
|
|
// I need to keep track of who owns how many stakes in the contract |
|
struct Record { |
|
uint id; |
|
address holder; |
|
uint shares; |
|
uint allowance; |
|
// check if record exists, open to a better way to do this |
|
bool exists; |
|
} |
|
mapping (address => Record) records; |
|
// Record[] records; |
|
// I want to eventually loop through all Shareholders |
|
// and create an allowance for them to withdraw |
|
|
|
event ProfitWithdrawn(address user, uint amount); |
|
event AllowanceUpdated(address user, uint totalAllowance, string reason); |
|
event TransferShares(address sender, address receiver, uint sharesSent); |
|
event NewMember(address user, uint memberId, uint shareBalance); |
|
|
|
modifier onlyShareholders { |
|
require(records[msg.sender].shares > 1); |
|
_; |
|
} |
|
|
|
function createNewMember(address _newMember, uint _initialShareBalance) private { |
|
// create a struct for member with _initialShareBalance or 0 shares |
|
// persist struct |
|
uint memberId = memberList.length; |
|
uint shares = _initialShareBalance > 1 ? _initialShareBalance : 0; |
|
Record memory newMemberStruct = Record(memberId, _newMember, shares, 0, true); |
|
records[_newMember] = newMemberStruct; |
|
memberList[memberId] = _newMember; |
|
|
|
NewMember(_newMember, memberId, _initialShareBalance); |
|
} |
|
|
|
function setAllowance(address _user, uint _newAllowance, string _reason) private { |
|
require(records[_user].shares > 1); |
|
// update member record to add newAllowance from balance |
|
Record storage member = records[_user]; |
|
member.allowance = _newAllowance; |
|
AllowanceUpdated(_user, member.allowance, _reason); |
|
} |
|
|
|
// trigger profit sharing |
|
function profitShare() onlyShareholders public { |
|
// make sure 30 days or share interval has passed |
|
require(now - lastProfitShare > profitShareInterval); |
|
// Create an allowance for each user based on their current stake |
|
// loop through all members and dish out their allowance based on last period's profit |
|
// period profit = profit |
|
for (uint _i = 0; _i < memberList.length; _i++) { |
|
address memberAdd = memberList[_i]; |
|
Record memory member = records[memberAdd]; |
|
// add allowance in amount of totalShares / memberList[i].shares * profit |
|
uint newAllowance = member.allowance + (totalShares / member.shares * profit); |
|
setAllowance(memberAdd, newAllowance, "profit share"); |
|
} |
|
// reset our running tab of profit for the period |
|
profit = 0; |
|
// set current time as most recent profit sharing |
|
lastProfitShare = now; |
|
} |
|
|
|
function withdrawProfits() onlyShareholders public { |
|
require(records[msg.sender].allowance != 0); |
|
// if user has an allowance, send it to them and set allowance to 0 |
|
Record storage member = records[msg.sender]; |
|
// transfer balance to sender |
|
msg.sender.transfer(member.allowance); |
|
ProfitWithdrawn(msg.sender, member.allowance); |
|
// reset allowance to 0 |
|
setAllowance(msg.sender, 0, "profit withdrawn"); |
|
} |
|
|
|
// stakeholder can send their shares to another user |
|
function sendShares(address _receiver, uint _sharesToSend) onlyShareholders public { |
|
// sender must have enough balance to cover shares they are sending |
|
require(records[msg.sender].shares >= _sharesToSend); |
|
|
|
// make sure user cant send shares to oblivion |
|
require(_receiver != 0x0); |
|
|
|
// grab modifiable versions of sender and receiver from storage |
|
Record storage receiver = records[_receiver]; |
|
Record storage sender = records[msg.sender]; |
|
|
|
if (receiver.exists) { |
|
// update existing member share total |
|
receiver.shares += _sharesToSend; |
|
|
|
} else { |
|
// create new member with share balance |
|
createNewMember(_receiver, _sharesToSend); |
|
} |
|
sender.shares -= _sharesToSend; |
|
TransferShares(msg.sender, _receiver, _sharesToSend); |
|
} |
|
} |