contract Foundation {
uint8 public maxDelegators;
uint8 public totalDelegators;
address public founder;
uint public debatingDays;
uint public numBudgets;
Budget[] public budgets;
Delegator[] public delegators;
struct Delegator {
address addr;
uint amount;
bytes32 bitcointalkId;
}
struct Budget {
address recipient;
uint amount;
bytes32 data;
string description;
uint creationDate;
uint confirmDate;
uint executeDays;
State state;
Vote[] votes;
mapping (address => uint8) voted;
}
/*
Created : member create a budget
Active: a member pro or con the bugdet within debatingDays( default =10 days)
Vetoed: over half of members against the budget, so budget was vetoed
Passed: over half pro the budget, passed th budget
Pending: after the recipient of the budget confirm the budget
Success: after the recipient has finished the job, over half of members agree a payment
Failed: recipient didnt finished the work in setting time
*/
enum State { Created, Active, Vetoed, Passed, Pending, Success, Failed }
event BudgetAdded(uint budgetID, address recipient, uint amount, bytes32 data, string description);
event BudgetVoted(uint budgetID, address voter, uint8 position);
event BudgetTallied(uint budgetID, uint8 reult, State state);
event BudgetConfirmed(uint budgetID, address recipient, State state);
event BudgetTicked(uint budgetID, address delegator, uint8 position);
event BudgetPaid(uint budgetID, uint8 tickDelegatorNum, uint amount);
struct Vote {
uint8 position;
address voter;
}
function Foundation(uint8 _maxDelegators, uint _debatingDays, bytes32 _bitcointalkId) {
founder = msg.sender;
maxDelegators = _maxDelegators;// || 5;
debatingDays = _debatingDays * 1 days;// || 10 days;
numBudgets = 0;
totalDelegators =0;
addDelegator(msg.sender, _bitcointalkId);
}
/* in the beginning, Creator adds the delegator
in the future, user will select delegators
*/
function addDelegator(address _addr, bytes32 _bitcointalkId) returns (uint8 totalDelegators)
{
if ( msg.sender == founder && totalDelegators < maxDelegators) {
Delegator d = delegators[totalDelegators++];
d.addr = _addr;
d.amount = _addr.balance;
d.bitcointalkId = _bitcointalkId;
}
}
modifier onlyDelegator()
{
for (uint8 i = 0; i < delegators.length; ++i) {
if (msg.sender == delegators[i].addr) break;
throw;
_
}
}
function newBudget(address _recipient, uint _amount, bytes32 _data, string _description)
onlyDelegator returns (uint BudgetID)
{
uint budgetID = budgets.length++;
Budget b = budgets[budgetID];
b.recipient = _recipient;
b.amount = _amount;
b.data = _data;
b.description = _description;
b.creationDate = now;
b.state = State.Created;
BudgetAdded(budgetID, _recipient, _amount, _data, _description);
numBudgets = budgetID+1;
}
/* 1= con , 2 =pro */
function voteBudget(uint _budgetID, uint8 _position)
onlyDelegator returns (uint voteID)
{
Budget b = budgets[_budgetID];
if ( (_position ==1 || _position ==2) && (b.state == State.Active || b.state == State.Created ) ) {
if (b.voted[msg.sender] > 0 ) return;
voteID = b.votes.length++;
b.votes[voteID] = Vote({position: _position, voter: msg.sender});
b.voted[msg.sender] = _position;
/* have a vote, budget active*/
if ( b.state != State.Active )
b.state = State.Active;
BudgetVoted(_budgetID, msg.sender, _position);
}
}
function executeBudget(uint _budgetID) returns (uint8 proDelegatorNum, State state)
{
Budget b = budgets[_budgetID];
/* Check if debating period is over */
if (now > (b.creationDate + debatingDays) && b.state == State.Active ){
proDelegatorNum = 0;
/* tally the votes */
for (uint i = 0; i < b.votes.length; ++i) {
Vote v = b.votes[i];
if (v.position == 2) ++proDelegatorNum;
}
/* execute result */
if (proDelegatorNum >= totalDelegators/2 ) {
b.state = State.Passed;
} else {
b.state = State.Vetoed;
}
BudgetTallied(_budgetID, proDelegatorNum, b.state);
}
}
function confirmBudget(uint _budgetID) returns (State result)
{
Budget b = budgets[_budgetID];
if ( msg.sender == b.recipient && b.state == State.Passed ){
b.state = State.Pending;
b.confirmDate = now;
BudgetConfirmed(_budgetID, b.recipient, b.state);
result = b.state;
}
//result = b.state
}
/* 1= pro, 2 = con,
5= tick, delegators who voted the budget can tick it ,then payment will happen
*/
function tickBudget(uint _budgetID, uint8 _position)
onlyDelegator returns (uint8 position)
{
Budget b = budgets[_budgetID];
if ( b.state == State.Pending && _position == 5 ) {
if (b.voted[msg.sender] == 0) return;
position = b.voted[msg.sender] + _position;
b.voted[msg.sender] = position;
/* have a vote, budget active*/
BudgetTicked(_budgetID, msg.sender, _position);
}
}
function budgetPayment(uint _budgetID) returns (uint8 tickDelegatorNum, uint8 result)
{
Budget b = budgets[_budgetID];
/* Check if executeDays is not overtime */
if ( b.state == State.Pending) {
if ( now <= b.confirmDate + b.executeDays ){
tickDelegatorNum = 0;
/* how many delegator agreed the payment */
for (uint i = 0; i < b.votes.length; ++i) {
Vote v = b.votes[i];
if (v.position > 5) ++tickDelegatorNum;
}
/* total of agreed is bigger than 1/2 delegators, will pay to recipient */
if (tickDelegatorNum >= totalDelegators/2 ) {
b.state = State.Success;
b.recipient.send(b.amount);
}
BudgetPaid(_budgetID, tickDelegatorNum, b.amount);
} else
b.state = State.Failed;
}
}
}
Foundation contract compiled success.