solidity实战-众筹项目

功能介绍

玩法

用户发起众筹->其他用户参与众筹

众筹可以提前关闭结束

众筹额度满了将不能继续参与

盈利

每个众筹成功的项目在提取时、合约将产生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

猜你喜欢

转载自blog.csdn.net/weixin_43840202/article/details/123368659