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;
        
    }
}

 

相关推荐

  1. solidity实战练习2--ERC20实现

    2024-07-14 14:36:02       23 阅读
  2. Solidity-6-合约

    2024-07-14 14:36:02       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 14:36:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 14:36:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 14:36:02       58 阅读
  4. Python语言-面向对象

    2024-07-14 14:36:02       69 阅读

热门阅读

  1. 【C语言】多进程服务器

    2024-07-14 14:36:02       28 阅读
  2. 日常学习--20240713

    2024-07-14 14:36:02       20 阅读
  3. qt 布局有多少种

    2024-07-14 14:36:02       18 阅读
  4. 并发漏洞介绍

    2024-07-14 14:36:02       18 阅读
  5. 展开说说:Android之View基础知识解析

    2024-07-14 14:36:02       16 阅读
  6. 代码随想录算法训练营第35天

    2024-07-14 14:36:02       20 阅读
  7. C++解压缩level2行情协议

    2024-07-14 14:36:02       27 阅读
  8. Day20—Scrapy与Redis的分布式爬取

    2024-07-14 14:36:02       22 阅读
  9. NLP入门之中文分词

    2024-07-14 14:36:02       20 阅读
  10. PSDK2003SP1/R2报__security_cookie的解决办法

    2024-07-14 14:36:02       29 阅读
  11. 二叉树---后序遍历(递归与迭代)

    2024-07-14 14:36:02       22 阅读
  12. 进制数相关

    2024-07-14 14:36:02       25 阅读