Created
January 13, 2020 14:12
-
-
Save josh-richardson/95cca5b07919230b6e7472218f2fa3fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.5.8; | |
import "@openzeppelin/contracts/math/SafeMath.sol"; | |
contract Campaign { | |
using SafeMath for uint256; | |
enum State { | |
Fundraising, | |
Funded, | |
Failed, | |
Successful | |
} | |
address payable public creator; | |
string public title; | |
string public description; | |
uint256 public currentBalance; | |
uint public goal; | |
uint public completeAt; | |
uint public raiseBy; | |
uint public successBy; | |
State public state = State.Fundraising; | |
uint public totalContributions = 0; | |
uint public stages; | |
uint256 public balancePerStage; | |
mapping (address => uint) public contributions; | |
mapping (address => uint) public votes; | |
uint public agrees = 0; | |
uint public currentStage = 1; | |
event FundingReceived(address contributor, uint amount, uint currentTotal); | |
event CreatorPaidStage(address recipient); | |
modifier inState(State _state) { | |
require(state == _state); | |
_; | |
} | |
modifier isCreator() { | |
require(msg.sender == creator); | |
_; | |
} | |
constructor | |
( | |
address payable _creator, | |
string memory _title, | |
string memory _description, | |
uint _stages, | |
uint _raiseBy, | |
uint _successBy, | |
uint _goal | |
) public { | |
creator = _creator; | |
title = _title; | |
description = _description; | |
stages = _stages; | |
goal = _goal; | |
successBy = _successBy; | |
raiseBy = _raiseBy; | |
agrees = 0; | |
} | |
function contribute() external inState(State.Fundraising) payable { | |
require(msg.sender != creator); | |
require(msg.value >= goal / 100); | |
if (contributions[msg.sender] == 0) { | |
totalContributions += 1; | |
} | |
contributions[msg.sender] = contributions[msg.sender].add(msg.value); | |
currentBalance = currentBalance.add(msg.value); | |
emit FundingReceived(msg.sender, msg.value, currentBalance); | |
checkFunded(); | |
} | |
function checkFunded() public { | |
if (currentBalance >= goal) { | |
balancePerStage = currentBalance.div(stages); | |
state = State.Funded; | |
} else if (now > raiseBy) { | |
state = State.Failed; | |
} | |
completeAt = now; | |
} | |
function vote() external inState(State.Funded) { | |
if (now > successBy) { | |
state = State.Failed; | |
revert(); | |
} | |
require(msg.sender != creator); | |
require(contributions[msg.sender] > 0); | |
require(votes[msg.sender] != currentStage); | |
votes[msg.sender] = currentStage; | |
agrees += 1; | |
if (agrees >= totalContributions / 2) { | |
agrees = 0; | |
payStage(); | |
if (currentStage == stages) { | |
state = State.Successful; | |
} else { | |
currentStage += 1; | |
} | |
} | |
} | |
function payStage() internal inState(State.Funded) returns (bool) { | |
uint256 totalRaised = currentBalance; | |
currentBalance = currentBalance.sub(balancePerStage); | |
if (creator.send(balancePerStage)) { | |
emit CreatorPaidStage(creator); | |
return true; | |
} else { | |
currentBalance = totalRaised; | |
state = State.Successful; | |
} | |
return false; | |
} | |
function getProperties() external view returns | |
( | |
address payable _creator, | |
string memory _title, | |
string memory _description, | |
uint256 _stages, | |
uint256 _currentStage, | |
uint256 _raiseBy, | |
uint256 _successBy, | |
State _state, | |
uint256 _currentBalance, | |
uint256 _goal | |
) { | |
_creator = creator; | |
_title = title; | |
_description = description; | |
_stages = stages; | |
_currentStage = currentStage; | |
_raiseBy = raiseBy; | |
_successBy = successBy; | |
_state = state; | |
_currentBalance = currentBalance; | |
_goal = goal; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment