Skip to content

Instantly share code, notes, and snippets.

@arthuRHD
Last active July 21, 2023 18:16
Show Gist options
  • Save arthuRHD/f7d48f168288408221edd7f038f0e604 to your computer and use it in GitHub Desktop.
Save arthuRHD/f7d48f168288408221edd7f038f0e604 to your computer and use it in GitHub Desktop.
Working on a way to crowdfund with ETH
pragma solidity ^0.8.0;
contract CrowdFund {
address public creator;
address public fundRecipient;
uint public minimumToRaise;
string campaignUrl;
uint8 constant version = 1;
enum State {
Fundraising,
ExpiredRefund,
Successful
}
struct Contribution {
uint amount;
address contributor;
}
State public state = State.Fundraising;
uint public totalRaised;
uint public raiseBy;
uint public completeAt;
Contribution[] public contributions;
event LogFundingReceived(address addr, uint amount, uint currentTotal);
event LogWinnerPaid(address winnerAddress);
modifier inState(State _state) {
require(state == _state, "Invalid state");
_;
}
modifier isCreator() {
require(msg.sender == creator, "Only creator can perform this action");
_;
}
modifier atEndOfLifecycle() {
require(((state == State.ExpiredRefund || state == State.Successful) && completeAt + 24 weeks < block.timestamp), "Contract still active");
_;
}
constructor (
uint timeInHoursForFundraising,
string memory _campaignUrl,
address _fundRecipient,
uint _minimumToRaise
) {
creator = msg.sender;
fundRecipient = _fundRecipient;
campaignUrl = _campaignUrl;
minimumToRaise = _minimumToRaise;
raiseBy = block.timestamp + (timeInHoursForFundraising * 1 hours);
}
function contribute() public payable inState(State.Fundraising) returns(uint256 id) {
contributions.push(
Contribution({
amount: msg.value,
contributor: msg.sender
})
);
totalRaised += msg.value;
emit LogFundingReceived(msg.sender, msg.value, totalRaised);
checkIfFundingCompleteOrExpired();
return contributions.length - 1;
}
function checkIfFundingCompleteOrExpired() public {
if (totalRaised > minimumToRaise) {
state = State.Successful;
payOut();
} else if (block.timestamp > raiseBy) {
state = State.ExpiredRefund;
}
completeAt = block.timestamp;
}
function payOut() public inState(State.Successful) {
payable(fundRecipient).transfer(address(this).balance);
emit LogWinnerPaid(fundRecipient);
}
function getRefund(uint256 id) inState(State.ExpiredRefund) public returns(bool) {
require(contributions.length > id && id >= 0 && contributions[id].amount != 0, "Invalid contribution ID");
uint256 amountToRefund = contributions[id].amount;
contributions[id].amount = 0;
payable(contributions[id].contributor).transfer(amountToRefund);
return true;
}
function removeContract() public isCreator() atEndOfLifecycle() {
selfdestruct(payable(msg.sender));
}
}
@arthuRHD
Copy link
Author

Working but not efficient. It's possible to cut costs even more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment