###淘宝众筹, 京东众筹
https://izhongchou.taobao.com/index.htm
###分析商业模式
https://z.jd.com/project/details/105705.html
期望的金钱流动
真实的金钱流动
控制金钱流动的方向, 速度.
众筹的金钱 进入智能合约中
每一笔开销,都要发起付款申请
投资人support付款申请.
选举投票决定项目是否继续进行
任何众筹项目都面临团队不负责任或者项目仅仅是一个骗局的风险,任何中心化投票系统都面临安全问题、贿赂选票和其他博弈上的缺陷。在 区块链系统中,这些风险都得到了最小化。
https://baijiahao.baidu.com/s?id=1606757323732765805&wfr=spider
名称 | 数据类型 | 说明 |
---|---|---|
manager | address | 众筹发起人地址(众筹发起人) |
projectName | string | 项目名称 |
supportMoney | uint | 众筹参与人需要付的钱 |
endTime | uint | 默认众筹结束的时间,为众筹发起后的一个月 |
goalMoney | uint | 目标募集的资金(endTime后,达不到目标则众筹失败) |
players | address[] | 众筹参与人的数组 |
requests | Request[] | 付款请求申请的数组 |
###函数设计
函数名称 | 函数说明 |
---|---|
Funding | 构造函数 |
support | 我要支持(需要付钱) |
createRequest | 付款申请函数,由众筹发起人调用 |
approveRequest | 付款批准函数, 由众筹参与人调用 |
finalizeRequest | 众筹发起人调用, 可以调用完成付款 |
moneyBack | 退钱函数, 由众筹发起人调用(众筹未成功时调用) |
pragma solidity ^0.4.17;
contract Funding{
address public manager;
string public projectName;
uint public supportMoney;
uint public endTime;
uint public goalMoney;
address[] public players;
function Funding(string _projectName,uint _supportMoney,uint _goalMoney) public{
projectName = _projectName;
supportMoney = _supportMoney;
goalMoney = _goalMoney;
endTime = now + 4 weeks;
manager = msg.sender;
}
}
address[] public players;
function support() public payable{
require(msg.value == supportMoney );
players.push(msg.sender);
}
#测试一下support函数
获取剩余天数
检查众筹状态
name | type | 说明 |
---|---|---|
description | string | 描述这笔付款请求是干啥的 |
money | uint | 花多少钱, 钱要少于balance |
shopAddress | address | 钱汇给谁. 真正的收钱方 |
complete | bool | true代表当前付款请求已经处理完毕 |
??? | ??? | 投票机制(大家先思考, 由众筹参与者决定) |
struct Request{
string description;
uint money;
address shopAddress;
bool complete;
}
只有经理可以createRequest
function createRequest(string _description, uint _money, address _shopAddress) public{
Request request = Request({
description:_description,
money:_money,
shopAddress:_shopAddress,
complete:false
});
requests.push(request);
}
##两种概念
##智能合约的数据存储
##solidity变量的数据存储
值传递和引用传递
memory值传递
storage引用传递
pragma solidity ^0.4.25;
contract Test{
uint[] public array;
function test() public{
array.push(11);
array.push(22);
// 引用传递 默认是storage, aa修改值会改变原来的数组值
uint[] aa = array;
aa[0] = 666;
// change(array);
}
// 值传递 默认 memory 内存复制的新对象, arr修改值不会改变原数组
function change(uint[] arr) {
arr[0] = 888;
}
// 强制改成storage类型, 必须声明成private, 合约内部函数才可调用, 此时可以修改原数组array的内容
function change2(uint[] storage arr) private{
arr[0] = 888;
}
function getArray() public view returns(uint[]) {
uint i = 9;
return array;
}
}
防止一个人重复投票
投票的人可能有很多(成千上万人)
没参与众筹没给钱,投个屁的票啊
一人一票不得违反
#投票逻辑的致命问题
有一些小砖(每块1英寸)和大砖(每块5英寸),我们想砌出来指定长度的墙,
如果用我们选择的砖块的数量能够拼接成功,则返回true;否则返回false,
例如:makeBricks(3, 1, 8) → true
[test.suits]
(3, 1, 8) -> true
(3, 1, 9) -> false
(3, 2, 10) -> true
(3, 2, 8) -> true
(3, 2, 9) -> false
(6, 1, 11) -> true
(6, 0, 11) -> false
(1, 4, 11) -> true
(0, 3, 10) -> true
(1, 4, 12) -> false
(3, 1, 7) -> true
(1, 1, 7) -> false
(2, 1, 7) -> true
(7, 1, 11) -> true
(7, 1, 8) -> true
(7, 1, 13) -> false
(43, 1, 46) -> true
(40, 1, 46) -> false
(40, 2, 47) -> true
(40, 2, 50) -> true
(40, 2, 52) -> false
(22, 2, 33) -> false
(0, 2, 10) -> true
(1000000, 1000, 1000100) -> true
(2, 1000000, 100003) -> false
(20, 0, 19) -> true
(20, 0, 21) -> false
(20, 4, 51) -> false
(20, 4, 39) -> true
代码运行的效率 vs 手续费
时间和金钱
#mapping重构代码
pragma solidity ^0.4.17;
contract Funding{
address public manager;
string public projectName;
uint public supportMoney;
uint public endTime;
uint public goalMoney;
address[] public players;
mapping(address => bool) playersMap;
Request[] public requests;
struct Request{
string description;
uint money;
address shopAddress;
bool complete;
mapping(address=>bool) approvedPlayers;
uint count;
}
function createRequest(string _description, uint _money, address _shopAddress) public{
require(msg.sender == manager);
Request memory request = Request({
description:_description,
money:_money,
shopAddress:_shopAddress,
complete:false,
count:0
});
requests.push(request);
}
function approveRequest(uint id) public{
require(playersMap[msg.sender]);
require(!requests[id].approvedPlayers[msg.sender]);
requests[id].count++;
requests[id].approvedPlayers[msg.sender] = true;
}
function finalizeRequest(uint id) public{
require(msg.sender == manager);
require(requests[id].count*2>players.length);
require(requests[id].money<=this.balance);
require(!requests[id].complete );
requests[id].shopAddress.transfer(requests[id].money);
requests[id].complete = true;
}
function Funding(string _projectName,uint _supportMoney,uint _goalMoney) public{
projectName = _projectName;
supportMoney = _supportMoney;
goalMoney = _goalMoney;
endTime = now + 4 weeks;
manager = msg.sender;
}
function support() public payable{
require(msg.value == supportMoney );
players.push(msg.sender);
playersMap[msg.sender] = true;
}
function getAccountBalance() public view returns(uint){
return this.balance;
}
}
#智能合约的部署
contract FundingFactory{
address[] public fundingAddress;
function createFunding(string _projectName,uint _supportMoney,uint _goalMoney) public{
address funding = new Funding(_projectName,_supportMoney,_goalMoney,msg.sender);
fundingAddress.push(funding);
}
}
#附件
第一版
pragma solidity ^0.4.17;
contract Funding{
bool flag = false;
//众筹发起人地址(众筹发起人)
address public manager;
//项目名称
string public projectName;
//众筹参与人需要付的钱
uint public supportMoney;
// 众筹结束的时间
uint public endTime;
// 目标募集的资金(endTime后,达不到目标则众筹失败)
uint public goalMoney;
// 众筹参与人的数组
address[] public players;
//付款请求申请的数组(由众筹发起人申请)
Request[] public requets;
// 付款请求的结构体
struct Request{
string description; // 为什么要付款
uint money; // 花多少钱
address shopAddress; // 卖家的钱包 地址
bool complete; // 付款是否已经完成
address[] votedAddress; // 哪些已经投过票的人
uint voteCount; // 投票的总的总数
}
function createRequest( string _description, uint _money, address _shopAddress) public onlyManagerCanCall{
require(this.balance >= _money);
Request memory request = Request({
description:_description,
money:_money,
shopAddress:_shopAddress,
complete:false,
votedAddress: new address[](0),
voteCount : 0
});
requets.push(request);
}
// 众筹参与人员批准某一笔付款 ( index数组的下标 )
function approveRequest(uint index) public {
Request storage request = requets[index];
bool supporter = false;
//1. 检查某个人是否已经在众筹参与人列表里面
for(uint i = 0;i<players.length;i++){
if( players[i] == msg.sender){
supporter = true;
}
}
require(supporter);
//2 .检查某个人是不是已经投过票了
bool voted = false;
for(uint j = 0; j<request.votedAddress.length;j++){
if( request.votedAddress[j] == msg.sender){
voted = true;
}
}
require(!voted);
request. voteCount ++;
request.votedAddress.push(msg.sender);
}
// 构造函数
function Funding(string _projectName,uint _supportMoney,uint _goalMoney) public{
manager = msg.sender;
projectName = _projectName;
supportMoney = _supportMoney;
goalMoney = _goalMoney;
endTime = now + 4 weeks;
}
// 参与人支持众筹
function support() public payable{
require(msg.value == 79);
players.push(msg.sender);
}
// 返回参与人的数量
function getPlayersCount() public view returns(uint){
return players.length;
}
function getPlayers() public view returns(address[]){
return players;
}
function getTotalBalance() public view returns (uint){
return this.balance;
}
function getRemainDays() public view returns(uint){
return (endTime - now)/24/60/60;
}
function checkStatus() public {
require(!flag);
require(now > endTime);
require(this.balance > goalMoney);
flag = true;
}
modifier onlyManagerCanCall(){
require(msg.sender == manager);
_;
}
}
##全套代码
pragma solidity ^0.4.25;
contract FundingFactory {
//存储所有已经部署的智能合约的地址
address[] public fundings;
function createFunding(string _projectName, uint _supportMoney, uint _goalMoney) public {
address funding = new Funding(_projectName, _supportMoney, _goalMoney, msg.sender);
fundings.push(funding);
}
function getFundings() public view returns(address[]){
return fundings;
}
}
contract Funding {
// 众筹成功标记
bool public flag = false;
// 众筹发起人地址(众筹发起人)
address public manager;
// 项目名称
string public projectName;
// 众筹参与人需要付的钱
uint public supportMoney;
// 目标募集的资金(endTime后,达不到目标则众筹失败)
uint public goalMoney;
// 默认众筹结束的时间,为众筹发起后的一个月
uint public endTime;
// 众筹参与人的数组
address[] public players;
mapping(address=>bool) playersMap;
// 付款请求的数组
Request[] public requests;
struct Request {
// 描述这笔付款请求是干啥的
string description;
// 花多少钱, 钱要少于balance
uint money;
// 钱汇给谁. 真正的收钱方
address shopAddress;
// 代表当前付款请求已经处理完毕
bool complete;
// 已投票的用户地址
mapping(address=>bool) votedMap;
uint votedCount;
}
//构造函数
constructor(string _projectName, uint _supportMoney, uint _goalMoney, address sender) public{
manager = sender;
projectName =_projectName;
supportMoney = _supportMoney;
goalMoney = _goalMoney;
endTime = now + 4 weeks;
}
// 我要支持(需要付钱)
function support() public payable{
require(msg.value == supportMoney);
// 放进集合中
players.push(msg.sender);
playersMap[msg.sender] = true;
}
// 付款申请函数,由众筹发起人调用
function createRequest(string _description, uint _money, address _shopAddress) public onlyManagerCanCall{
// 余额大于等于付款请求
require(address(this).balance >= _money);
Request memory request = Request({
description: _description,
money: _money,
shopAddress: _shopAddress,
complete: false,
votedCount: 0
});
requests.push(request);
}
// 付款批准函数, 由众筹参与人调用
function approveRequest(uint index) public {
// 是否是众筹参与者
require(playersMap[msg.sender]);
// 防止一个人重复投票
Request storage request = requests[index];
require(!request.votedMap[msg.sender]);
request.votedMap[msg.sender] = true;
request.votedCount++;
}
// 众筹发起人调用, 可以调用完成付款
function finalizeRequest(uint index) public onlyManagerCanCall{
Request storage request = requests[index];
require(!request.complete);
// 钱够
require(address(this).balance >= request.money);
// 人数过半
require(request.votedCount * 2 >= getPlayersCount());
// 执行转账操作
request.shopAddress.transfer(request.money);
request.complete = true;
}
// 所有参与者
function getPlayers() public view returns(address[]){
return players;
}
// 所有参与者个数
function getPlayersCount() public view returns(uint){
return players.length;
}
// 获取合约的余额
function getTotalBalance() public view returns(uint){
return address(this).balance;
}
// 获取剩余天数
function getRemainDays() public view returns(uint) {
return (endTime - now) / 60 / 60 / 24;
}
// 检查众筹状态
function checkStatus() public onlyManagerCanCall {
require(!flag);
// 到期
require(now >= endTime);
// getTotalBalance金额>= goalMoney
require(address(this).balance >= goalMoney);
flag = true;
}
modifier onlyManagerCanCall {
require(msg.sender == manager);
_;
}
}