本合約是一個比較完整的眾籌合約掘殴,含:新建眾籌項目,轉(zhuǎn)賬粟誓,打款奏寨,以及退款等功能!
編寫合約時鹰服,可以直接在線上編寫和測試部署
聲明結(jié)構(gòu)體和變量
參與者只需記錄參與者的地址和捐贈的金額
struct funder {
address funderAddress; // 捐贈者地址
uint toMoney; // 捐贈money
}
發(fā)起者則需要較多的屬性服爷,如:受益地址,目標(biāo)金額获诈,是否募資完成等H栽础!舔涎!
另外笼踩,要通過funderMap(mapping)將捐贈者的id與捐贈者綁定在一起,從而得知是誰給受益人捐錢亡嫌。
struct needer {
address payable neederAddress; // 受益人地址
uint goal; // 眾湊總數(shù)(目標(biāo))
uint amount; // 當(dāng)前募資金額
uint isFinish; // 募資是否完成
uint funderAccount; // 當(dāng)前捐贈者人數(shù)
mapping(uint => funder) funderMap; // 映射嚎于,將捐贈者的id與捐贈者綁定在一起,從而得知是誰給受益人捐錢
}
聲明發(fā)起眾湊的項目挟冠,并且通過neederMap(mapping)將受益人id與收益金額綁定在一起于购,從而可以更好的管理受益人
address payable owner; // 合約發(fā)起者地址
uint neederAmount; // 眾籌項目id
mapping (uint => needer) neederMap; // 通過mapping將受益人id與收益金額綁定在一起,從而可以更好的管理受益人
實例眾湊項目
create眾湊項目的時候知染,直接給定一個自增的序號當(dāng)作當(dāng)前眾湊項目的id肋僧。create項目時,要根據(jù)前面聲明的needer結(jié)構(gòu)體實例,參數(shù)要一一對應(yīng)嫌吠。
/*
* _neederAddress: 受益人地址(項目發(fā)起者)
* _goal: 眾籌目標(biāo)
*/
function NewNeeder(address payable _neederAddress, uint _goal) public {
owner = msg.sender;
neederAmount++;
neederMap[neederAmount] = needer(address(_neederAddress), _goal, 0, 0, 0);
}
捐贈者參與捐贈(轉(zhuǎn)賬)
捐贈可以根據(jù)眾湊項目id給該項目捐錢(轉(zhuǎn)賬)止潘,當(dāng)合約的方法發(fā)生轉(zhuǎn)賬時必須用到payable關(guān)鍵字。另外辫诅,要先校驗捐贈者錢包余額夠不夠本次捐贈的余額凭戴,還有校驗該項目是否已終止,判斷都有效的情況炕矮,此時會將本次捐贈的金額直接轉(zhuǎn)賬到當(dāng)前合約中么夫,同時記錄捐贈人數(shù)和記錄捐贈者。
// 捐贈者給指定眾籌id打錢
/*
*_neederAmount: 眾籌項目id
*_address: 捐贈者地址
*/
function contribue(address _address, uint _neederAmount) public payable {
require(msg.value > 0);
needer storage _needer = neederMap[_neederAmount]; // 獲取眾籌項目
require(_needer.isFinish == 0); // 募資是否完成肤视, 若完成則取消當(dāng)前捐款
_needer.amount += msg.value; // 捐贈金額
_needer.funderAccount++; // 捐贈者個數(shù)
_needer.funderMap[_needer.funderAccount] = funder(_address, msg.value); // 標(biāo)記捐贈者及捐贈金額
}
項目結(jié)束档痪,轉(zhuǎn)賬給受益人(也是屬于轉(zhuǎn)賬)
結(jié)束項目的原因有多種,但是這里只是用捐贈完成的原因作為例子钢颂。捐贈完成后钞它,可以由合約發(fā)起者(本合約中也是受益者)發(fā)起將合約的錢轉(zhuǎn)到自己的錢包地址中拜银,這里同樣發(fā)生了交易殊鞭,所以也要用到關(guān)鍵字payable。然而尼桶,我們發(fā)現(xiàn)該方法中有一個onlyOwner修飾詞操灿,onlyOwner在下面會聲明,表示只能是合約發(fā)起者才能調(diào)用該方法泵督。
// 捐贈是否完成趾盐,若完整,給受益人轉(zhuǎn)賬
/*
*_neederAmount: 眾籌項目id
*/
function Iscompelete(uint _neederAmount) public payable onlyOwner {
needer storage _needer = neederMap[_neederAmount]; // 獲取眾籌項目
require(_needer.amount >= _needer.goal);
_needer.neederAddress.transfer(_needer.amount);
_needer.isFinish = 1; // 若完成募資小腊,則取消繼續(xù)募資
}
退錢(也是屬于轉(zhuǎn)賬)
當(dāng)捐款的完成后救鲤,由于合約沒有銷毀,捐贈者還是可以繼續(xù)捐贈的秩冈,因此會導(dǎo)致多出的錢仍在合約賬戶中本缠,所以就有了該退款的方法。該方法是將合約上的錢根據(jù)捐贈者退回給捐贈者入问。
// 募資完成時丹锹,退款給捐贈人
function returnBack(uint _neederAmount) public payable {
needer storage _needer = neederMap[_neederAmount]; // 獲取眾籌項目
require(_needer.funderMap[_needer.funderAccount].funderAddress == msg.sender);
uint returnMoney = _needer.funderMap[_needer.funderAccount].toMoney;
uint balance = address(this).balance;
balance -= returnMoney;
msg.sender.transfer(returnMoney);
}
查詢已募資金額(合約的錢)
// 查詢合約余額
function getBalance() public view returns(uint) {
return address(this).balance;
}
查詢募資狀態(tài)
// 查看募資狀態(tài)
function showData(uint _neederAmount) public view returns(uint, uint, uint, uint) {
return (neederMap[_neederAmount].goal, neederMap[_neederAmount].isFinish, neederMap[_neederAmount].amount, neederMap[_neederAmount].funderAccount);
}
聲明合約擁有者
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
合約銷毀
function kill() public {
require(msg.sender == owner);
selfdestruct(owner);
}