Skip to content

Instantly share code, notes, and snippets.

@aesthezel
Created April 21, 2022 18:20
Show Gist options
  • Save aesthezel/662696ecd4af3f7150bea799860f3ea7 to your computer and use it in GitHub Desktop.
Save aesthezel/662696ecd4af3f7150bea799860f3ea7 to your computer and use it in GitHub Desktop.
A crowdfunding smart contract example
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract CrowdFunding
{
uint private projectIdCounter;
struct Contribution
{
address contributor;
uint ammount;
}
enum ProjectState {Open, Close}
struct Project
{
uint id;
string name;
string description;
address payable author;
ProjectState state;
uint funds;
uint goal;
}
Project[] public projects;
mapping(uint => Contribution[]) public contributions;
event OnProjectCreated
(
uint id,
string name,
string description,
uint goal
);
event OnProjectFounded
(
uint projectId,
uint ammount,
ProjectState state
);
event OnProjectStateChange
(
uint projectId,
ProjectState state
);
error HandleStateNotDefined(ProjectState exception);
// Decorator Pattern
modifier isAuthor(uint projectIndex)
{
require
(
msg.sender == projects[projectIndex].author,
"Only owner can change the project name"
);
_; // Continue the wrapped function
}
modifier isNotAuthor(uint projectIndex)
{
require
(
msg.sender != projects[projectIndex].author,
"Founder don't collaborate in own projects"
);
_;
}
function createProject(string calldata name, string calldata description, uint goal) public
{
bytes memory nameInBytes = bytes(name);
require(goal > 0, "Goal must be greater than 0");
require(nameInBytes.length > 0 , "Name can't be empty");
Project memory project = Project(projectIdCounter, name, description, payable(msg.sender), ProjectState.Open, 0, goal);
projects.push(project);
emit OnProjectCreated(projectIdCounter, name, description, goal);
projectIdCounter++;
}
function fundProject(uint projectIndex) public payable isNotAuthor(projectIndex)
{
Project memory project = projects[projectIndex];
require(project.state != ProjectState.Close, "The project is closed! Can't receive more funds...");
require(msg.value > 0, "Fund value most be greater than 0");
project.author.transfer(msg.value);
project.funds += msg.value;
if(project.funds >= project.goal)
{
project.state = ProjectState.Close;
}
contributions[project.id].push(Contribution(msg.sender, msg.value));
projects[projectIndex] = project;
emit OnProjectFounded(project.id, msg.value, project.state);
}
function changeProjectState(uint projectIndex, ProjectState newState) public isAuthor(projectIndex)
{
Project memory project = projects[projectIndex];
require(project.state != newState, "The new state must be different");
if(newState == ProjectState.Open || newState == ProjectState.Close)
{
project.state = newState;
emit OnProjectStateChange(project.id, project.state);
projects[projectIndex] = project;
}
else
{
revert HandleStateNotDefined(newState);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment