Loading...
Crowdfunding is the use of small amounts of capital from a large number of individuals to finance a new business venture.
Anyone will be able to list his/her project for crowdfunding in smart contract.
Create a function where each project will have unique Id. You can ask for some details like project name, expected cost, starting date, finishing date, etc while registering for particular project for crowdfunding. After registering for crowdfunding the contract owner will verify the details and validate it. Once owner has validated for the project, it is available for public to fund the project. Anyone can see the project details and ID accordingly they will transfer their funds from own wallet to the smart contract. HINT : Create a function fundproject(id) and take id as parameter. Save this details in a mapping (id => uint) projectfundbalance.
After the funding process is completed the particular project owner can withdraw his/her collected funds from smart contract.
First we will declare all the state variables that we need in our smart contract.
pragma solidity 0.8.2;
contract Crowdfunding{
//State variables
address public Manager;
uint256 totalFunds; //total funds funded in contract
uint256 start; //to set current time
uint256 end; //to set duration
uint256 public counter; //to create project ids
}
We have to take Project details so for that we will declare struct. Struct "Project" consist of all the details related to Project.
struct Project{
uint256 id;
address payable owner;
string projectName;
string description;
uint256 expectedCost;
uint256 fundedamt;
uint256 isRegistered;
uint256 isVerified;
uint256 fundwithdraw;
}
In this, we have taken 3 variables isRegistered, isVerified, fundwithdraw which is used as a flag. You can use Boolean here but instead of boolean we are using uint256, because boolean takes much space to store so to reduce gas cost for the contract we are using uint256. The values for this variable will change only in between 0 & 1.
Here we are declaring constructor in which deployer of the smart contract will be the Manager who will validate the Projects. Also we are declaring duration for funding. So within that time limit, anyone can send fund for the projects. Project Owners can withdraw funds only after the completion of duration.
constructor(uint256 _duration){
Manager = msg.sender; //it will set deployer as a validator
start = block.timestamp; //it will take the current time as a start time
end = (_duration * 1 days) + start; //it will show the end date of funding
}
mapping(address => uint256)public ProjectId;
mapping(uint256 => Project) public Projects;
mapping(uint256 => uint256) public ProjectFunds;
event ProjectRegistered(uint256 _id,uint256 _rtime,string _name,address _owner);
event ProjectIsVerified(uint256 _pid,uint256 _time);
event FundsTransferred(uint256 _pid,uint256 _time,address _from,uint256 _fund);
event FundsWithdrawn(uint256 _pid,uint256 _time,address _to,uint256 _fund);
modifier onlyManager(){
require(msg.sender==Manager,"You are not Manager");
_;
}
We have declare three Mappings,
There are 4 Events & one Modifier. Modifier is for Managers access.
function regProject(string memory _pname,string memory _desc,uint256 _cost) public {
require(block.timestamp < end, "Duration is over");
require(msg.sender != Manager && ProjectId[msg.sender]== 0,"Manager and existing owners of projects not able to register again");
counter++;
Project memory pro = Project(counter,payable (msg.sender),_pname,_desc,_cost,1,0,0,0);
ProjectId[msg.sender] = counter;
Projects[counter] = pro;
emit ProjectRegistered(counter, block.timestamp, _pname, msg.sender);
}
function verifyProject(uint256 _id) public onlyManager() {
Projects[_id].isVerified = 1;
emit ProjectIsVerified(_id,block.timestamp);
}
function viewProject(uint256 _id) public view returns(uint256,address,string memory,string memory,uint256,uint256,uint256){
require(Projects[_id].isVerified == 1,"Project is not verified");
return (
Projects[_id].id,
Projects[_id].owner,
Projects[_id].projectName,
Projects[_id].description,
Projects[_id].expectedCost,
Projects[_id].isRegistered,
Projects[_id].fundedamt
);
}
function sendFunds(uint256 _id) payable public {
require(block.timestamp < end, "The funding duration is over");
require(Projects[_id].isVerified == 1 && msg.sender != Projects[_id].owner && Projects[_id].fundwithdraw == 0,"you are owner or project is unverified");
Projects[_id].fundedamt += msg.value;
totalFunds++;
ProjectFunds[_id] = msg.value;
emit FundsTransferred(_id,block.timestamp,msg.sender,msg.value);
}
function withdrawFunds(uint256 _id) public payable {
require(block.timestamp > end, "The funding duration is not over yet");
require(msg.sender == Projects[_id].owner,"You are not owner of this project");
address payable add = Projects[_id].owner;
Projects[_id].fundedamt-=ProjectFunds[_id];
add.transfer(ProjectFunds[_id]);
Projects[_id].fundwithdraw +=ProjectFunds[_id];
emit FundsWithdrawn(_id,block.timestamp,add,ProjectFunds[_id]);
}
function TimeLeft() public view returns(uint256) {
require(block.timestamp <= end, "The funding duration is over");
return end - block.timestamp;
}
function contractBal() public view returns(uint256){ //this function is optional
return address(this).balance;
}
We have created total 5 main functions as follows:
Our final code will look like:
pragma solidity 0.8.2;
contract Crowdfunding{
//state variable
address public Manager;
uint256 totalFunds;
uint256 start;
uint256 end;
uint256 public counter;
//Struct
struct Project{
uint256 id;
address payable owner;
string projectName;
string description;
uint256 expectedCost;
uint256 isRegistered;
uint256 isVerified;
uint256 fundedamt;
uint256 fundwithdraw;
}
constructor(uint256 _duration){
Manager = msg.sender;
start = block.timestamp;
end = (_duration * 1 days) + start;
}
//mappings
mapping(address => uint256)public ProjectId;
mapping(uint256 => Project) public Projects;
mapping(uint256 => uint256) public ProjectFunds;
//events
event ProjectRegistered(uint256 _id,uint256 _rtime,string _name,address _owner);
event ProjectIsVerified(uint256 _pid,uint256 _time);
event FundsTransferred(uint256 _pid,uint256 _time,address _from,uint256 _fund);
event FundsWithdrawn(uint256 _pid,uint256 _time,address _to,uint256 _fund);
//modifiers
modifier onlyManager(){
require(msg.sender==Manager,"You are not Manager");
_;
}
//functions
function regProject(string memory _pname,string memory _desc,uint256 _cost) public {
require(block.timestamp < end, "Duration is over");
require(msg.sender != Manager && ProjectId[msg.sender]== 0,"Manager and existing owners of projects not able to register again");
counter++;
Project memory pro = Project(counter,payable (msg.sender),_pname,_desc,_cost,1,0,0,0);
ProjectId[msg.sender] = counter;
Projects[counter] = pro;
emit ProjectRegistered(counter, block.timestamp, _pname, msg.sender);
}
function verifyProject(uint256 _id) public onlyManager() {
Projects[_id].isVerified = 1;
emit ProjectIsVerified(_id,block.timestamp);
}
function viewProject(uint256 _id) public view returns(uint256,address,string memory,string memory,uint256,uint256,uint256){
require(Projects[_id].isVerified == 1,"Project is not verified");
return (
Projects[_id].id,
Projects[_id].owner,
Projects[_id].projectName,
Projects[_id].description,
Projects[_id].expectedCost,
Projects[_id].isRegistered,
Projects[_id].fundedamt
);
}
function TimeLeft() public view returns(uint256) {
require(block.timestamp <= end, "The funding duration is over");
return end - block.timestamp;
}
function sendFunds(uint256 _id) payable public {
require(block.timestamp < end, "The funding duration is over");
require(Projects[_id].isVerified == 1 && msg.sender != Projects[_id].owner && Projects[_id].fundwithdraw == 0,"you are owner or project is unverified");
Projects[_id].fundedamt += msg.value;
totalFunds++;
ProjectFunds[_id] = msg.value;
emit FundsTransferred(_id,block.timestamp,msg.sender,msg.value);
}
function contractBal() public view returns(uint256){
return address(this).balance;
}
function withdrawFunds(uint256 _id) public payable {
require(block.timestamp > end, "The funding duration is not over yet");
require(msg.sender == Projects[_id].owner,"You are not owner of this project");
address payable add = Projects[_id].owner;
Projects[_id].fundedamt-=ProjectFunds[_id];
add.transfer(ProjectFunds[_id]);
Projects[_id].fundwithdraw +=ProjectFunds[_id];
emit FundsWithdrawn(_id,block.timestamp,add,ProjectFunds[_id]);
}
}
This is basic crowdfunding smart contract, you can use openzeppline too.