solidity实战练习5——众筹合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IERC20 {
function transfer(address, uint) external returns (bool);
function transferFrom( address, address,uint ) external returns (bool);
}
interface crowdFund{
function launch( uint _goal,uint32 _startAt,uint32 _endAt ) external;//发起众筹
function cancel(uint _id) external;//发起者取消众筹
function pledge(uint _id, uint _amount) external;//用户参与众筹
function unpledge(uint _id, uint _amount) external ;//用户取消众筹
function claim(uint _id) external;//众筹成功,发起者可以调走众筹的代币
function refund(uint _id) external;//众筹失败,用户领取自己的代币
}
contract CrowdFund {
event Launch(uint id,address indexed creator,uint goal,uint32 startAt,uint32 endAt);
event Cancel(uint id);
event Pledge(uint indexed id, address indexed caller, uint amount);
event Unpledge(uint indexed id, address indexed caller, uint amount);
event Claim(uint id);
event Refund(uint id, address indexed caller, uint amount);
struct Campaign {//这个相当一个类,每次发起一个合约都需要实例化一下这个类
//确定众筹合约的创建者
address creator;
//确定合约众筹的目标
uint goal;
//当前众筹合约众筹的总量
uint pledged;
// 开始时间
uint32 startAt;
//结束时间
uint32 endAt;
//是否完成?
bool claimed;
}
IERC20 public immutable token; // 指定token
uint public count=0;//标记当前合约所含有的众筹合约的个数
uint record=0;//记录总合约被捐款次数
mapping(uint => Campaign) public campaigns;// 众筹合约的编号与众筹合约一一对应
mapping(uint => mapping(address => uint)) public pledgedAmount;//id->个人address->捐款总额
mapping(uint =>mapping(address=>uint) ) private recordParticipantValue;//ID->address->value
mapping(uint => mapping(uint=>address)) private participantRecord;//ID->捐款编号->address
constructor(address _token) {//通过构造函数来确认代币的类型
token = IERC20(_token);
}
modifier isStart(uint _id)//函数修改器,确保被修饰函数需要进行开始检查
{
require(block.timestamp >= campaigns[_id].startAt,"not start");
_;
}
modifier isEnd(uint _id)//函数修改器,确保被修饰函数需要进行结束检查
{
require(block.timestamp<=campaigns[_id].endAt,"ended");
_;
}
modifier checkId(uint _id){
require(_id<=count,"your id is wrong");
_;
}
function launch(uint _goal,uint32 _startAt,uint32 _endAt) external {//发起合约的具体定义
require(_startAt >= block.timestamp, "start at < now");
require(_endAt > _startAt, "end at < start at");
require(_endAt <= block.timestamp + 90 days, "end at > max duration");//持续时间默认为90天,通过开始时间来定义结束时间
campaigns[count] = Campaign({
creator: msg.sender,
goal: _goal,
pledged: 0,
startAt: _startAt,
endAt: _endAt,
claimed: false
});
count += 1;
emit Launch(count, msg.sender, _goal, _startAt, _endAt);
}
function cancel(uint _id) external checkId( _id) {//合约发起之后可能由于筹集目标过高,想要删除这次众筹
Campaign memory campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
autoRefund( _id);//调用自动退还功能,被删除合约自动发送所有的代币给参与合约的用户
delete campaigns[_id];
emit Cancel(_id);
}
function pledge(uint _id, uint _amount) external payable isStart(_id) isEnd(_id) checkId( _id){
Campaign storage campaign = campaigns[_id];
require(_amount > 0,"your amount is error");
require(msg.value==_amount,"money is error");
participantRecord[_id][record]=msg.sender;
recordParticipantValue[record][msg.sender]=_amount;
record+=1;
campaign.pledged += _amount;
pledgedAmount[_id][msg.sender] += _amount;
token.transferFrom(msg.sender, address(this), _amount);
emit Pledge(_id, msg.sender, _amount);
}
function unpledge(uint _id, uint _amount) external isStart(_id) isEnd(_id) checkId( _id){
require(_amount<=pledgedAmount[_id][msg.sender],"your amount is wrong");
Campaign storage campaign = campaigns[_id];
campaign.pledged -= _amount;
pledgedAmount[_id][msg.sender] -= _amount;
token.transfer(msg.sender, _amount);
emit Unpledge(_id, msg.sender, _amount);
}
function claim(uint _id) external checkId( _id) {
Campaign storage campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged >= campaign.goal, "pledged < goal");
require(!campaign.claimed, "claimed");
campaign.claimed = true;
token.transfer(campaign.creator, campaign.pledged);
emit Claim(_id);
}
function refund(uint _id) external isStart(_id) checkId( _id){
Campaign memory campaign = campaigns[_id];
require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged < campaign.goal, "pledged >= goal");
uint bal = pledgedAmount[_id][msg.sender];
pledgedAmount[_id][msg.sender] = 0;
token.transfer(msg.sender, bal);
emit Refund(_id, msg.sender, bal);
}
function autoRefund(uint _id)private isStart(_id) checkId( _id){
Campaign memory campaign = campaigns[_id];
for(uint i=0;recordParticipantValue[i][participantRecord[_id][i]]!=0;i++)
{
token.transfer(participantRecord[_id][i],recordParticipantValue[i][ participantRecord[_id][i]]);
pledgedAmount[_id][participantRecord[_id][i]]=0;
}
campaign.pledged=0;
}
}
原文地址:https://blog.csdn.net/2303_79193185/article/details/140415725
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!