eth day05
智能合约众筹实战
淘宝众筹,京东众筹
https://izhongchou.taobao.com/index.htm
分析商业模式

解决京东众筹的痛点

https://izhongchou.taobao.com/dreamdetail.htm?spm=a215p.1596646.2.14.107f75e3s6qjBj&&id=20078649
期望的金钱流动

真实的金钱流动

控制金钱流动的方向, 速度.
众筹的金钱 进入智能合约中

每一笔开销,都要发起付款申请

投资人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函数
查看一下当前智能合约余额
查看当前众筹参与人员players信息
付款的Request结构体
| name | type | 说明 |
|---|---|---|
| description | string | 描述这笔付款请求是干啥的 |
| money | uint | 花多少钱, 钱要少于balance |
| shopAddress | address | 钱汇给谁. 真正的收钱方 |
| complete | bool | true代表当前付款请求已经处理完毕 |
| ??? | ??? | 投票机制(大家先思考, 由众筹参与者决定) |
struct Request{
string description;
uint money;
address shopAddress;
bool complete;
}
createRequest
只有经理可以createRequest
function createRequest(string _description, uint _money, address _shopAddress) public{
Request request = Request({
description:_description,
money:_money,
shopAddress:_shopAddress,
complete:false
});
requests.push(request);
}
memory和storage

- storage
- memory
两种概念
- 智能合约如何存储数据, 是在memory还是storage
- solidity变量如何存储数据, 是在memory还是在storage
智能合约的数据存储
- storage : 成员变量. 可以跨函数调用. 有点类似于硬盘
- memory: 临时数据存储, 类似于电脑的内存 函数的参数可以理解为memory类型

solidity变量的数据存储
值传递和引用传递
memory值传递
storage引用传递
pragma solidity ^0.4.24;
contract Test {
uint[] public array;
function test() public{
array.push(1);
array.push(2);
uint[] memory b = array;
b[0] = 33;
changeArray(array);
}
function changeArray(uint[] array) public{
array[0] = 1;
}
}
投票系统需求

防止一个人重复投票

投票的人可能有很多(成千上万人)
投票系统设计稿 业务逻辑
- 检查某个人是否已经在众筹参与人列表里面
没参与众筹没给钱,投个屁的票啊
- 检查某个人是不是已经投过票了
一人一票不得违反
投票逻辑的致命问题
有一些小砖(每块1英寸)和大砖(每块5英寸),我们想砌出来指定长度的墙,
如果用我们选择的砖块的数量能够拼接成功,则返回true;否则返回false,
例如:makeBricks(3, 1, 8) → true
测试用例 (每行显示一条测试用例,格式为(参数1,参数2) -> 期望结果)
[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);
playersMap[msg.sender] = true;
}
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);
}
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{
//众筹发起人地址(众筹发起人)
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{
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;
}
modifier onlyManagerCanCall(){
require(msg.sender == manager);
_;
}
}
全套代码
pragma solidity ^0.4.17;
contract FundingFactory{
//存储所有已经部署的智能合约的地址
address[] public fundings;
function deploy(string _projectName,uint _supportMoney,uint _goalMoney) public{
address funding = new Funding(_projectName,_supportMoney,_goalMoney, msg.sender);
fundings.push(funding);
}
}
contract Funding{
//众筹发起人地址(众筹发起人)
address public manager;
//项目名称
string public projectName;
//众筹参与人需要付的钱
uint public supportMoney;
// 众筹结束的时间
uint public endTime;
// 目标募集的资金(endTime后,达不到目标则众筹失败)
uint public goalMoney;
// 众筹参与人的数组
address[] public players;
mapping(address=>bool) playersMap;
//付款请求申请的数组(由众筹发起人申请)
Request[] public requets;
// 付款请求的结构体
struct Request{
string description; // 为什么要付款
uint money; // 花多少钱
address shopAddress; // 卖家的钱包 地址
bool complete; // 付款是否已经完成
mapping(address=>bool) votedmap; // 哪些已经投过票的人
uint voteCount; // 投票的总的总数
}
function createRequest( string _description, uint _money, address _shopAddress) public onlyManagerCanCall{
Request memory request = Request({
description:_description,
money:_money,
shopAddress:_shopAddress,
complete:false,
voteCount : 0
});
requets.push(request);
}
// 众筹参与人员批准某一笔付款 ( index数组的下标 )
function approveRequest(uint index) public {
Request storage request = requets[index];
//1. 检查某个人是否已经在众筹参与人列表里面
require(playersMap[msg.sender]);
//2 .检查某个人是不是已经投过票了
require(!requets[index].votedmap[msg.sender]);
request. voteCount ++;
requets[index].votedmap[msg.sender] = true;
}
//众筹发起人调用, 可以调用完成付款 index 下标
function finalizeRequest(uint index) public onlyManagerCanCall {
Request storage request = requets[index];
// 付款 必须是 未 处理的
require(!request.complete);
// 至少一半以上的参与者 同意付款
require(request.voteCount * 2 >players.length );
// 打钱 转账
require(this.balance>=request.money);
request.shopAddress.transfer(request.money);
request.complete = true;
}
// 构造函数
function Funding(string _projectName,uint _supportMoney,uint _goalMoney, address _address) public{
manager = _address;
projectName = _projectName;
supportMoney = _supportMoney;
goalMoney = _goalMoney;
endTime = now + 4 weeks;
}
// 参与人支持众筹
function support() public payable{
require(msg.value == supportMoney);
players.push(msg.sender);
//设置mapping集合
playersMap[msg.sender] = true;
}
// 返回参与人的数量
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;
}
modifier onlyManagerCanCall(){
require(msg.sender == manager);
_;
}
}
eth day05的更多相关文章
- TCP/IP协议学习(三) STM32中ETH驱动配置注意事项
1.MII/RMII/SMI接口连接和配置 SMI又称站点管理接口,用于cpu与外置PHY芯片通讯,配置相关参数,包含MDC和MDIO两个管脚(CPU上有对应引脚,当然用普通GPIO口模拟SMI管理也 ...
- My way to Python - Day05 - 面向对象-思维导图
My way to Python - Day05 - 面向对象 思维导图
- 是否可能两个ETH私钥对应同一个地址
原提问在这里. 笔者在使用到neon-js中的私钥生成方法时发现其使用了getRandomValues方法来生成64字符长度的私钥,进而考虑到其随机性,若是调用足够多次,依然有可能生成两个完全一样的私 ...
- day05 Servlet 开发和 ServletConfig 与 ServletContext 对象
day05 Servlet 开发和 ServletConfig 与 ServletContext 对象 1. Servlet 开发入门 - hello world 2. Servlet 的调用过程和生 ...
- js 校验 btc eth 地址
NPM 安装 npm install wallet-address-validator Browser <script src="wallet-address-validator.mi ...
- centos7将网卡名字改成eth样式
ll /etc/sysconfig/grub lrwxrwxrwx 1 root root 17 Jun 12 2016 /etc/sysconfig/grub -> /etc/default/ ...
- python day05笔记总结
2019.4.2 S21 day05笔记总结 一.昨日内容回顾与补充 1.extend(列表独有功能) 循环添加到一个列表中 a.有列表users = ['张三',‘李四] people = [' ...
- 以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- Python基础(协程函数、内置函数、递归、模块和包)-day05
写在前面 上课第五天,打卡: 凭着爱,再回首: 一.协程函数(生成器:yield的表达式形式) 1.yield 的语句形式: yield 1 - 这种方式在 Python基础(函数部分)-day04 ...
随机推荐
- Xshell中使用FTP/SFTP工具下载文件
(1)sftp host_ip,输入用户名/密码 (2)通过cd命令找到远程服务器要拷贝的文件: 通过lcd命令指定本地保存地址. (3)通过get filename拷贝文件 (4)在本地查看,已经可 ...
- Python基础—08-函数使用(02)
函数使用 生成器 使用场景: 在使用列表时,很多时候我们都不会一下子使用全部的数据,通常都是一个一个使用,但是数据量较小的时候,对于内存的占用可以不用过于关心:但是当数据量较大时,就会出现内存使用突然 ...
- rest_framework -- 认证组件
#####认证组件##### 一.认证是什么就不说了,某些网页必须是用户登陆之后,才能访问的,所以这时候就需要用上认证组件. 你不用rest_framework的认证组件也行,这种认证的话,完全可以自 ...
- plupload批量上传分片(后台代码)
plupload批量上传分片功能, 对于文件比较大的情况下,plupload支持分片上传,后台代码如下: /** * * 方法:upLoadSpecialProgramPictrue * 方法说明:本 ...
- 【TOJ 1449】Area of Circles II(求不同位置的两圆面积之和)
描述 There are two circles on the plane. Now you must to calculate the area which they cover the plane ...
- 在C++中如何实现文件的读写
一.ASCII 输出为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstream>取代< fstream.h>,所 ...
- 解决WordPress设置错误的url网站不能访问的问题
通过WordPress后台首选项更改了网站url地址之后,网站就会出现访问不了的情况,一般来说,网站后台也登陆不上去了,我从网上寻找到了四种方法,这四种方法前三种都是需要登陆到后台的,但实际上出错后, ...
- python的字典数据类型及常用操作
字典的定义与特性 字典是Python语言中唯一的映射类型. 定义:{key1: value1, key2: value2} 1.键与值用冒号“:”分开: 2.项与项用逗号“,”分开: 特性: 1.ke ...
- 消费滚动滴log日志文件(flume监听,kafka消费,zookeeper协同)
第一步:数据源 手写程序实现自动生成如下格式的日志文件: 15837312345,13737312345,2017-01-09 08:09:10,0360 打包放到服务器,使用如下命令执行,模拟持续不 ...
- ecshop 全系列版本网站漏洞 远程代码执行sql注入漏洞
ecshop漏洞于2018年9月12日被某安全组织披露爆出,该漏洞受影响范围较广,ecshop2.73版本以及目前最新的3.0.3.6.4.0版本都受此次ecshop漏洞的影响,主要漏洞是利用远程代码 ...