功能介绍
玩法
用户发起众筹->其他用户参与众筹
众筹可以提前关闭结束
众筹额度满了将不能继续参与
盈利
每个众筹成功的项目在提取时、合约将产生5%的扣点,扣点收益将全部交给合约管理员,管理员需要手动提取
实现代码
pragma solidity ^0.6.0;
contract Financing {
// 出资人
struct Donor {
uint amount;//融资金额
address addr;//地址
uint time;//融资时间
}
// 融资发起人
struct Sponsor {
uint amount; // 当前已融资金额
uint max_amount;//需要融资金额
string name;//名称
address addr;//地址
uint start_time;//发起时间
uint end_time;//结束时间
uint financing_num;//融资地址数
mapping(uint => Donor) map;//融资人
}
// 发起人自增id
uint public sponsorId;
// 发起人信息
mapping(uint => Sponsor) public sponsorMap;
// 已完成的融资
mapping(uint => bool) public finishMap;
//管理员
address admin;
// 扣点 5%
uint deduction = 5;
// 利润
uint public profit = 0;
constructor(address admin_) public {
admin = admin_;
}
// 提取利润
function extractProfit_() public {
admin.call{
value : profit}('');
}
// 发起融资项目
function createFinancing(uint amount_, string memory name_, uint end) public {
// 最少融资时常1天
if (end - now < 86400) {
end = now + 86400;
}
sponsorMap[sponsorId] = Sponsor(0, amount_, name_, msg.sender, now, end, 0);
sponsorId ++;
}
// 给项目融资
function donate(uint sponsorId_) public payable {
// 判断是否结束
require(!isEnd(sponsorId_), 'Financing completed');
// 判断支付的钱是否小于0
require(msg.value > 0, 'donate amount is 0');
// 找出融资的发起人
Sponsor storage sponsor_ = sponsorMap[sponsorId_];
// 判断有没有发起时间,没有的话表示没有这个项目
require(sponsor_.addr != address(0), 'notfund fundraising');
sponsor_.financing_num ++;
sponsor_.amount += msg.value;
// 设置当前的融资信息,key为当前融资的个数
sponsor_.map[sponsor_.financing_num] = Donor(msg.value, msg.sender, now);
}
// 定义事件
event TakeOut(string name, address addr, uint start_time, uint end_time, uint financing_num, uint amount);
// 结束并取出
function endAndTakeOut(uint sponsorId_) public {
require(!finishMap[sponsorId_], 'the financing is end');
Sponsor storage sponsor_ = sponsorMap[sponsorId_];
// 判断当前id是不是你的
require(msg.sender == sponsor_.addr, 'Illegal withdrawal');
// 结束当前项目
finishMap[sponsorId_] = true;
// 取出前扣点扣点
uint amount_ = sponsor_.amount * (deduction / 100);
// 已融资金额大于0,转给发起融资地址
if (sponsor_.amount > 0) {
// 收取扣点
profit = profit + sponsor_.amount - amount_;
// 发给募资发起人
sponsor_.addr.call{
value : amount_}('');
}
// 执行成功发事件
emit TakeOut(sponsor_.name, sponsor_.addr, sponsor_.start_time, sponsor_.end_time, sponsor_.financing_num, amount_);
}
// 判断是否结束
function isEnd(uint sponsorId_) public view returns(bool){
Sponsor storage sponsor_ = sponsorMap[sponsorId_];
return finishMap[sponsorId_] || sponsor_.end_time < now;
}
// 查询地址已经发布的融资id
function getFinancing(address addr_) public view returns (uint[] memory) {
// 先查找出地址在map中的数量
uint num = 0;
for (uint i = 0; i < sponsorId; i++) {
if (sponsorMap[i].addr == addr_) {
num ++;
}
}
// 数量初始化数组
uint[] memory ids = new uint[](num);
uint k = 0;
for (uint j = 0; j < sponsorId; j++) {
if (sponsorMap[j].addr == addr_) {
ids[k] = j;
k++;
}
}
return ids;
}
}
abi
[
{
"inputs": [
{
"internalType": "address",
"name": "admin_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "name",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "addr",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "start_time",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "end_time",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "financing_num",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "TakeOut",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "amount_",
"type": "uint256"
},
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "uint256",
"name": "end",
"type": "uint256"
}
],
"name": "createFinancing",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "sponsorId_",
"type": "uint256"
}
],
"name": "donate",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "sponsorId_",
"type": "uint256"
}
],
"name": "endAndTakeOut",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "extractProfit_",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "finishMap",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "addr_",
"type": "address"
}
],
"name": "getFinancing",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "sponsorId_",
"type": "uint256"
}
],
"name": "isEnd",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "profit",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "sponsorId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "sponsorMap",
"outputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "max_amount",
"type": "uint256"
},
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "address",
"name": "addr",
"type": "address"
},
{
"internalType": "uint256",
"name": "start_time",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "end_time",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "financing_num",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
demo仅供交流学习
运算建议用safeMath.sol