基于Solidity以及Dapp的众筹合约项目

1.创建众筹项目

在这里我们将众筹项目使用结构体来封装起来,可以记录下该项目创建的地址,给我们的众筹项目起个标题,增加描述,这个众筹的钱是拿来干嘛的,还可以记录我们的目标金额以及筹到的金额,项目开始的时间以及结束的时间,时间结束之后钱是否被提取,以及参与众筹的人数。一下代码就是项目的结构体

  struct _Project {
        address creator;
        string title;
        string des;
        uint256 goalMoney;
        uint256 pledged;
        uint256 startTime;
        uint256 endTime;
        bool extracted;
        uint256 projectPeople;
    }

2.参与众筹

我们要创建一个函数,用来发起众筹,用户可以根据自己的需求来创建众筹的项目,但是在创建时会有一些限制性的条件。比如项目的结束时间不能比开始时间早(我们用时间戳来比较)、需要筹的钱不能小于项目要求的数额、同一个人是不能重复捐款的、判断时间是否还在规定的范围内,在捐款之后我们要记录下捐款人的金额、时间以及将它标记为捐过的状态,同时给捐款的人给予一个ERC20的代币奖励

    //用户参与众筹
    function pledge(uint256 _id) public payable{
        Project storage project = projects[_id];
        require(block.timestamp >= project.startTime, "not start");
        require(block.timestamp <= project.endTime, "end");
        require(msg.value >= 2 , "amount<2eth"); //不低于2eth
        require(msg.value + project.pledged <= project.goalMoney* 1e18, "amount>goalMoney");
        require(!contributors[msg.sender], "already contribut"); // 判断是否已经付款
        require(
            contributionTimes[_id][msg.sender] <= block.timestamp,
            "too soon to contribute again"
        );
        project.pledged +=msg.value;
        pledgedMoney[_id][msg.sender] += msg.value;
        contributors[msg.sender] = true; // 标记为已付款
        contributionTimes[_id][msg.sender] = block.timestamp; // 记录付款时间
        project.projectPeople++; //计算参与众筹的人数
       token.transfer(msg.sender, 1); // 发送1个代币给捐款人  
        emit Pledge(_id, msg.sender, msg.value);
    }

3.众筹项目查询

由于运用了一个映射来存储众筹合约的内容,这里的uint256也就代表着每个项目的编号(id),输入相应的编号,我们能看见该项目的捐款人数、捐款金额以及目标金额等等

  mapping(uint256 =>Project) public projects;

4.提取资金

定义一个函数来提取众筹成功后的金额,在提取前也会有要求,看提取人是否在可提取余额的账户列表之内,如果在则可以提取,同时也要满足众筹的金额满足目标的金额,以及众筹的时间已经结束,提取之后会将该地址赋予一个标记,以防止重复提取金额,之后再触发事件

    //发起众筹的人当要求满足时可以取出金额
    function extracted(uint256 _id) external {
        Project storage project = projects[_id];
        for (uint256 i = 0; i < accounts.length; i++) {
            // 检查账户是否在可用提取的账户列表中
            require(
               contains(accounts, msg.sender),
                "Account not found in the list of available accounts"
            );
        }
        // require(block.timestamp > project.endTime, "not ended");
        require(project.pledged >= project.goalMoney* 1e18, "pledged < goal");
        require(!project.extracted, "claimed");
        project.extracted = true;
        payable(msg.sender).transfer(project.pledged);
        emit Extracted(_id);
    }

5.退款机制

如果众筹项目未达到目标金额,在截止日期到达后,参与者可以请求退款。

  //当资金未满可以取消参与的众筹
    function unpledge(uint256 _id) external payable {
        Project storage project = chengjinjin_projects[_id];
        require(block.timestamp <= project.endTime, "ended");
        project.pledged -= msg.value;
        pledgedMoney[_id][msg.sender] -= msg.value;
        payable(msg.sender).transfer(msg.value);
    }

6.增加提取余额用户

添加可以提取合约余额的账户列表功能

定义一个函数来增加提取余额的账户,当发起众筹的用户想要添加可以提取的账户地址,同时也会有一定的限制,调用改函数的账户一定要是该项目的创建者,同时众筹的余额要满足项目需要的金额,将该新的账户地址标记为false

  // 添加一个新的账户到合约中
    function addAccount(uint256 _id, address _newAccount) public {
        Project storage project = projects[_id];
        require(project.creator == msg.sender, "not creator");
        require(project.pledged >= project.goalMoney* 1e18, "pledge < goalMoney");
        require(!project.extracted, "claimed");
        accounts.push(_newAccount);
        project.extracted = false; // 重置已领取状态为false
    }

7.取消用户提取余额权限

当项目的创建者想要取消一些账户的提取余额权限,就可以取消该地址提取余额的权利,在提取余额账户列表的数组中遍历得到要取消权限的地址,如果找到,将该地址移除合法权限列表

   //移除提取余额的用户
    function removeAccount(uint256 _id, address _accountToRemove)
        public
    {
        Project storage project = projects[_id];
        require(project.creator == msg.sender, "not authorized");
        uint256 indexToRemove = 0;
        for (uint256 i = 0; i < accounts.length; i++) {
            if (accounts[i] == _accountToRemove) {
                indexToRemove = i;
                break;
            }
        }
        // 从数组中移除用户遍历
        for (uint256 i = indexToRemove; i < accounts.length - 1; i++) {
            accounts[i] = accounts[i + 1];
        }
        accounts.pop();
    }

8.在Matemask上进行部署合约,同时要使用自己的私链

9.效果图前端页面

10.项目的创建

11.投资人捐款

​​​​​​​

12.捐款成功可以获得一个代币的奖励

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的小西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值