Crowdfunding contract for smart contract development

Realizing a good idea takes a lot of effort and requires a lot of money. It is possible to seek user donations, or to invest in institutional investment, but it is often difficult. Blockchain provides a new form of crowdfunding - crowdfunding smart contract development . The fundraiser sets the crowdfunding target and completion time through the crowdfunding contract, and sets the operations corresponding to different crowdfunding results (for example, if the target fails, the full amount will be returned, and the beneficiary will receive encrypted tokens or ETH when the target is successful). Due to the immutable nature of the blockchain, the development of crowdfunding smart contracts would be a very suitable application scenario. In this article, we will use Ethereum solidity to implement a smart contract development for crowdfunding , and give the final solidity code.

Tokens and Distributed Autonomous Organizations

In this example we will do better crowdfunding by addressing two important issues:

  • How to manage funds and ensure liquidity;
  • How to spend your money after raising money.

Crowdfunding projects before the emergence of blockchain generally lack liquidity. Once investors miss the deadline for crowdfunding, they will not be able to participate in crowdfunding; once they participate in crowdfunding, investors cannot withdraw halfway. Smart contracts record investment amounts by issuing tokens and provide liquidity similar to the stock market. Investors can choose to trade or continue to hold. After the project is successful, investors can use tokens to exchange for physical goods or product services. If the project fails, investors can withdraw according to the original agreement and continue to hold tokens to commemorate.

Similarly, the current crowdfunding project also has the problem of unclear where the funds go. In this project, we use DAO (Distributed Autonomous Organization) to record where every money goes.

Smart contract development code

Put the code first, and then read it step by step.

pragma solidity ^0.4.16;
interface token {
    function transfer(address receiver, uint amount);
}

contract Crowdsale {
    address public beneficiary;
    uint public fundingGoal; 
    uint public amountRaised; 
    uint public deadline; 
    uint public price;
    token public tokenReward;
    mapping(address => uint256) public balanceOf;
    bool fundingGoalReached = false; 
    bool crowdsaleClosed = false; 
    event GoalReached(address recipient, uint totalAmountRaised); 
    event FundTransfer(address backer, uint amount, bool isContribution); 
    /** * Constrctor function * * Setup the owner */
    function Crowdsale(
        address ifSuccessfulSendTo, 
        uint fundingGoalInEthers,        
        uint durationInMinutes,        
        uint etherCostOfEachToken,
        address addressOfTokenUsedAsReward    
    ) {
        beneficiary = ifSuccessfulSendTo;
        fundingGoal = fundingGoalInEthers * 1 ether;
        deadline = now + durationInMinutes * 1 minutes;
        price = etherCostOfEachToken * 1 ether;
        tokenReward = token(addressOfTokenUsedAsReward);
    }
    /** * Fallback function * * The function without name is the default function that is called whenever anyone sends funds to a contract */
    function () payable {
        require(!crowdsaleClosed); 
        uint amount = msg.value;
        balanceOf[msg.sender] += amount;
        amountRaised += amount;
        tokenReward.transfer(msg.sender, amount / price);
        FundTransfer(msg.sender, amount, true);
    }
    modifier afterDeadline() {
        if (now >= deadline) _; 
    }
    /** * Check if goal was reached * * Checks if the goal or time limit has been reached and ends the campaign */
    function checkGoalReached() afterDeadline { 
       if (amountRaised >= fundingGoal){
            fundingGoalReached = true;
            GoalReached(beneficiary, amountRaised);
        }
        crowdsaleClosed = true;
    }
    /** * Withdraw the funds * * Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached, * sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw * the amount they contributed. */
    function safeWithdrawal() afterDeadline { 
       if (!fundingGoalReached) { 
            uint amount = balanceOf[msg.sender];
            balanceOf[msg.sender] = 0; 
           if (amount > 0) { 
               if (msg.sender.send(amount)) {
                    FundTransfer(msg.sender, amount, false);
                } else {
                    balanceOf[msg.sender] = amount;
                }
            }
        } 
        if (fundingGoalReached && beneficiary == msg.sender) { 
            if (beneficiary.send(amountRaised)) {
                FundTransfer(beneficiary, amountRaised, false);
            } else { 
                //If we fail to send the funds to beneficiary, unlock funders balance
                fundingGoalReached = false;
            }
        }
    }
}

in the constructor

fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;

ether and minutes are keywords reserved by Ethereum, 1 ether == 1000 finney , 2 days == 48 hours. The keywords for date types include seconds, minutes, hours, days, weeks, and years, and the reserved keywords for ether units include wei, finney, szabo, and ether. 1 finney == 1000 szabo, 1 szabo == 10^12 wei. now is also a keyword reserved by Ethereum, representing the current time.

Next we instantiate a contract:

tokenReward = token(addressOfTokenUsedAsReward);
token的定义在代码开头:

interface token { 
    function transfer(address receiver, uint amount){  }
}

Here we don't implement the token contract, we just tell the compiler that our token is a contract, has a transfer() function, and has this contract at the given address.

Next, let's see how the contract receives funds. The relevant code is as follows:

function () {    
    require(!crowdsaleClosed);
    uint amount = msg.value;
    // ...

This function is very special. It has no name. In solidity, we call it a fallback function. The fallback function has no parameters and no return value. If the contract receives ether, a fallback function must be explicitly defined, otherwise an exception will be fired and ether will be returned. The function that receives ether must have the keyword payable, otherwise an error will be reported.

The require statement first determines whether the crowdfunding has ended. If the crowdfunding has ended, the money will be returned to the calling party to avoid unnecessary losses to the calling party.

After the deployment is passed, you can use your own test account to transfer money to the contract address, so that you can participate in crowdfunding.

After the crowdfunding is successful, if you continue to transfer money to the contract address, the money will be returned to your account.

Isn't it hard to develop a crowdfunding smart contract?

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325830735&siteId=291194637