这篇博客将完成一个经典的众筹合约:
1.思路:
1)为某个账户或者合约申请一个众筹账号
2)允许其他账号对此众筹账户进行捐赠
3)检查现有金额是否已经大于目标金额,如果是则将众筹账号注销,将钱转给众筹所指定的人
2.代码
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
contract crowd_funding{
//众筹账号的结构体,分别为,众筹接受捐赠的地址,目标金额,现有金额和捐赠者到其捐赠金额的映射
struct receiver{
address payable rece;
uint goal;
uint amount;
// uint donaNum;
mapping(address => uint)moneyAccount;
}
//捐赠者的结构体
struct donator{
address dona;
uint funds;
}
uint num=0;
//从众筹编号到众筹账号的映射,众筹编号用于捐赠或者查询时指定想要捐赠的账号
mapping(uint => receiver)fundAccount;
//初始众筹账号
function applyForDonate(address payable account,uint goalMoney) public{
num++;
fundAccount[num]=receiver(account,goalMoney,0);
}
//一开始想要传递结构体,但是结构体做参数需要internal修饰
//而internal又会和payable矛盾从而使contribute无法使用transfer()
/*function contriute(uint _num,address _ad,uint _fund) public{
donator memory _temp=donator(_ad,_fund);
process(_num,_temp);
}*/
function contribute(uint _num)public payable{
//这样就可以用一个编号来获取一个众筹账号
//并且使用storage避免离开此函数就使得众筹账号无效
receiver storage temp=fundAccount[_num];
//msg.sender无法和uint比较
//require(msg.sender>0);
temp.amount+=msg.value;//**look this!可以直接将ether加到变量上**
// temp.donaNum++;
temp.moneyAccount[msg.sender]+=msg.value;
}
function check(uint _num,address payable target) public payable returns(string memory){
receiver storage temp=fundAccount[_num];
require(temp.amount>=temp.goal);
target.transfer(temp.amount);
temp.amount=0;
// selfdestruct(temp.rece);
return "this crowd funding is completed!";
}
//获得某个账号在某个众筹捐的钱的数额
function getAccountMoney(address _ad,uint _num) public view returns(uint){
receiver storage temp1=fundAccount[_num];
return temp1.moneyAccount[_ad];
}
//获得某个众筹的当前众筹金额和目标金额
function getPrensent(uint _num) public view returns(uint,uint){
receiver storage temp2=fundAccount[_num];
return (temp2.amount,temp2.goal);
}
}
3.过程
1)首先申请一个众筹账号,并通过getPresent知道需要众筹10000wei
2)选择如下账户,选择捐赠10000wei给0号众筹账号
可以看到余额变成了10000
3)点击check函数给目标账户,10000wei成功转账
4.总结
此众筹项目确实十分简单,但也是我的第一个solidity项目,因此还是挺开心的。但也有不少地方可以再完善,如:一个申请众筹的地址应该设有申请上限,应当实时监控众筹是否已经完成目标并自动转账给目标账户或者设置一个捐赠时间等。我还只是刚刚开始,等我更加熟悉solidity后再来将此项目进一步完善(flag);