Skip to content

Instantly share code, notes, and snippets.

@0xrusowsky
Last active July 23, 2022 19:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xrusowsky/5b583aeff7e387fa00652a9b079c34ad to your computer and use it in GitHub Desktop.
Save 0xrusowsky/5b583aeff7e387fa00652a9b079c34ad to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;
// Task 2. Implement the backbone for a simple Crowdfunding platform with the following requirements:
// - Anyone can create a campaign to acquire funding for their project
// - Each campaign must have (at least!):
// - A name
// - An owner
// - A campaign type
// - A funding goal (in Eth)
// - A time limit to reach it, which can't be higher than 60 days
// - All of the above properties must be defined at campaign creation, and can't be updated.
// - Campaigns can be of 2 types: Start-up and Charity
// - Until the time limit of a given campaign is reached anyone can fund it by sending Eth. After time limit is reached, it can't receive any more funds.
// - An owner of a campaign can withdraw the raised Eth only after time limit was reached.
// - After the owner withdraws the funds, campaigns should be marked either as Fully-Funded (if raised >= funding goal) or Partially-Funded (if raised < funding goal)
// - An owner must be able to cancel a campaign. If this happens that campaign can't receive any more Eth.
// - Implement all the events you see relevant
contract Campaign {
enum CampaignType {
StartUp,
Charity
}
enum CampaignOutcome {
PartiallyFunded,
FullyFunded
}
string public name;
address payable public owner;
CampaignType public campaignType;
uint256 public goal;
uint256 public deadline;
CampaignOutcome public campaignOutcome;
bool public canceled;
constructor(
string memory _name,
address _owner,
CampaignType _type,
uint256 _goal,
uint256 _deadline
) {
require(_deadline <= 5184000, "Max length of 60 days");
name = _name;
owner = payable(_owner);
campaignType = _type;
goal = _goal;
deadline = block.timestamp + _deadline;
}
/* == EVENTS ================================== */
event NewDonation(uint256 indexed timestamp, address indexed sender, uint256 amount);
event CampaignClosure(uint256 timestamp, uint256 valueRaised);
event Withdraw(uint256 timestamp, address receiver, uint256 amount);
/* == MODIFIERS ================================== */
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier liveCampaign() {
require(block.timestamp <= deadline, "Deadline closed");
require(!canceled, "Canceled campaign");
require(address(this).balance - msg.value <= goal, "Goal reached");
_;
}
modifier redeemableCampaign() {
require(block.timestamp >= deadline, "Not redeemable yet");
_;
}
/* == FUNCTIONS ================================== */
fallback() external payable liveCampaign {
emit NewDonation(block.timestamp, msg.sender, msg.value);
}
receive() external payable liveCampaign {
emit NewDonation(block.timestamp, msg.sender, msg.value);
}
function withdrawFunds(address receiver)
public
payable
onlyOwner
redeemableCampaign
{
uint256 funds = address(this).balance;
(bool sent, ) = receiver.call{value: funds}("");
require(sent, "Failed to withdraw");
emit Withdraw(block.timestamp, receiver, funds);
campaignOutcome = (
funds >= goal
? CampaignOutcome.FullyFunded
: CampaignOutcome.PartiallyFunded
);
}
function cancelCampaign() public payable onlyOwner liveCampaign {
canceled = true;
}
}
contract CrowdFundFactory {
mapping(address => uint8) public userCampaigns;
mapping(address => Campaign[]) public userCampaignContracts;
/* == EVENTS ================================== */
event NewCampaign(
string campaignName,
address campaignAddress,
address owner,
uint256 indexed timestamp
);
/* == FUNCTIONS ================================== */
function createCampaign(
string memory _name,
Campaign.CampaignType _type,
uint256 _goal,
uint32 _deadline
) public {
Campaign newCampaign = new Campaign(
_name,
msg.sender,
_type,
_goal,
_deadline
);
userCampaigns[msg.sender]++;
userCampaignContracts[msg.sender].push(newCampaign);
emit NewCampaign(_name, address(newCampaign), msg.sender, block.timestamp);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment