Crowdfunding Smart Contract

This smart contract enables a user to:

  • Create a crowdfunding contract
  • Set a minimum contribution amount
  • Establish a target amount
  • Specify a deadline

Once the target amount is reached, the contract owner can refund the Ether, either partially or in full. However, a voting mechanism requires that 51% of the contributors vote for this action.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;

contract CrowdFunding {
    mapping(address => uint) public Contributors;
    address public Manager;
    uint public minContribution;
    uint public deadline;
    uint public target;
    uint public raiseAmount;
    uint public noOfContributors;

    struct Request {
        string description;
        address payable recipient;
        uint value;
        bool isCompleted;
        uint noOfVoters;
        mapping(address => bool) voters;
    }

    mapping(uint => Request) public requests;
    uint public numRequests;

    constructor(uint _target, uint _deadline) {
        target = _target;
        deadline = block.timestamp + _deadline;
        minContribution = 100 wei;
        Manager = msg.sender;
    }

    function sendEth() public payable {
        require(block.timestamp < deadline, "deadline has been passed");
        require(msg.value >= 100 wei, "Minimum Contribution is not met");

        if (Contributors[msg.sender] == 0) {
            noOfContributors++;
        }

        Contributors[msg.sender] += msg.value;
        raiseAmount += msg.value;
    }

    function getContractBalance() public view returns (uint) {
        return address(this).balance;
    }

    function refund() public {
        require(block.timestamp > deadline && raiseAmount < target);
        require(Contributors[msg.sender] > 0);
        address payable user = payable(msg.sender);
        user.transfer(Contributors[msg.sender]);
        Contributors[msg.sender] = 0;
    }

    modifier onlyManager() {
        require(msg.sender == Manager, "only manager can call this function");
        _;
    }

    function createRequest(
        string memory _description,
        address payable _recipient,
        uint _value
    ) public onlyManager {
        Request storage newRequest = requests[numRequests];
        numRequests++;
        newRequest.description = _description;
        newRequest.recipient = _recipient;
        newRequest.value = _value;
        newRequest.isCompleted = false;
        newRequest.noOfVoters = 0;
    }

    function voteRequest(uint _requestNo) public {
        require(Contributors[msg.sender] > 0, "you are not a contributor");
        Request storage thisRequest = requests[_requestNo];
        require(
            thisRequest.voters[msg.sender] == false,
            "you have aready voted"
        );
        thisRequest.voters[msg.sender] = true;
        thisRequest.noOfVoters++;
    }

    function makePayment(uint _requestNo) public onlyManager {
        require(raiseAmount >= target, "Target amount has not been reached");
        Request storage thisRequest = requests[_requestNo];
        require(
            thisRequest.isCompleted == false,
            "Already distributed the amount"
        );
        require(
            thisRequest.noOfVoters > noOfContributors / 2,
            "majority support marks not crossed"
        );
        thisRequest.recipient.transfer(thisRequest.value);
        thisRequest.isCompleted = true;
    }
}

Testing with Remix

Open the https://remix.ethereum.org/. Create ‘Crowdfunding.sol’ file and paste the code inside.

  • Deploy the Smart Contract on Remix

Set the ‘TARGET’ to 1000 wei and the ‘DEADLINE’ to 3600 seconds for testing purposes.

Click the ‘transact’ button to deploy the contract.

  • Add Contributors to the Contract

In Remix, select different accounts and transfer Ether to the contract, making sure the amount is more than 100 wei. Attempting to send less than 100 wei will result in an error.

All parameters can be retrieved from the contract once the contributions have been made.

  • Make a Refund Request

Contract owner can create a request for a refund.

To set up a refund request, select the Manager account and navigate to the ‘createRequest’ field in the contract. Enter the following parameters:

  • description: “test”
  • recipient: “Address that will receive the Ether”
  • value: 400 (The value of the request)

Click the ‘Transact’ button.

After submitting the request, you can view its status by clicking the ‘request’ button: 0 (the first request is numbered 0).

  • Voting for the Request

Choose a contributor account and proceed to the ‘voteRequest’ field.

Input ‘requestNo’ as 0, which represents the current request number.

Press the ‘transact’ button.

After casting your vote successfully, verify the request status once more. The ‘noOfVoters’ parameter should now reflect the update to 1.

Continue the same voting process for other contributors until you reach 51%.

  • Withdraw the Requested Amount

Choose the Manager account and proceed to the ‘makePayment’ field.

Input ‘requestNo’ as 0.

Click the ‘transact’ button.