实现一个好的idea须要付出巨大努力,并须要大量资金。能够寻求用户捐赠,或投资机构投资,但每每很难。 区块链提供了一种众筹的新形式——众筹智能合约开发。募资人经过众筹合约设定好众筹目标,以及完成时间,设定不一样众筹结果所对应的操做(例如目标失败退回全款、目标成功时受益人得到加密代币或ETH)。因为区块链不可篡改的特性,开发众筹智能合约会是一个很是吻合的应用场景。在本文中,咱们将使用以太坊solidity来实现一个用于众筹的智能合约开发,并给出最终实现的solidity所有代码。app
这个例子中咱们将经过解决两个重要的问题进行更好的众筹:分布式
区块链出现以前的众筹项目通常缺乏流动性,投资人一旦错过众筹截止时间将没法参与众筹;一旦参与众筹,投资人也不能中途退出。智能合约经过发行代币的形式来记录投资额,并提供了相似股票市场的流动性。投资人能够选择交易或者继续持有。项目成功后投资者可使用代币交换实物或者产品服务。项目失败的话投资者能够按照原先的约定退出,而且继续持有代币以表记念。ide
一样,当前众筹项目也存在资金去向不明的问题。在这个项目中,咱们使用DAO(分布式自治组织)记录每一笔资金去向。函数
先放上代码,而后再一步步解读。区块链
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; } } } }
构造函数中测试
fundingGoal = fundingGoalInEthers * 1 ether; deadline = now + durationInMinutes * 1 minutes;
ether和minutes是以太坊预留的关键字,1 ether == 1000 finney , 2 days == 48 hours。日期类型的关键字有seconds,minutes,hours, days,weeks,years,以太币单位预留的关键字有wei,finney,szabo,ether。1 finney == 1000 szabo,1 szabo == 10^12 wei。now也是以太坊预留的关键字,表明当前时间。ui
接下来咱们实例化了一个合约:加密
tokenReward = token(addressOfTokenUsedAsReward); token的定义在代码开头: interface token { function transfer(address receiver, uint amount){ } }
这里咱们并未实现token合约,只是告诉编译器咱们的token是一个合约,具备一个transfer()函数,而且在给定的地址上有这个合约。idea
接下来咱们看看合约如何接收资金,相关代码以下:spa
function () { require(!crowdsaleClosed); uint amount = msg.value; // ...
这个函数很特别,它没有名字,在solidity中咱们称之为回退函数(Fallback function),回退函数没有参数,也没有返回值。若是合约接收ether,则必须明肯定义回退函数,不然会触发异常,并返回ether。接收ether的函数必须带有关键字payable,不然会报错。
require语句先判断众筹是否结束,若是众筹已经结束,钱将退回给主叫方,避免主叫方出现没必要要的损失。
部署经过以后能够用本身的测试帐户向合约地址转帐,这样就能够参与众筹了。
众筹成功后,若是继续往合约地址转帐,钱将会退回你的帐户。
开发一个众筹智能合约是否是也不是很难?