以太坊彩票DAPP实战(一)

一、业务分析

在区块链上部署彩票Dapp的优点:

1)代码公开透明,接收所有人的监督;

2)没有暗箱操作,不存在跑路的风险;

彩票规则:

1)全民参与;

2)每人可以多次投注,但每次只投一注(一注就是1个 eth);

3)只有管理员才能够执行开奖和退奖的操作,其他账户只有投注功能;

二、投注

奖金池用于保存投注的金额,彩民池保存了参与投注的彩民。

image-20180912183822218

当投注后,奖金池的金额会发生变化,同样投注的帐号也会添加到彩民池中。

image-20180912184029036

三、开奖

由管理员负责开奖,开奖后会把奖金池的金额转给中奖的账户,然后奖金池和彩民池的数据都会被清空。

 

四、退奖

由管理员负责退款。执行退款后,系统会把奖金池中的金额退还给每一个参与的账户,然后奖金池和彩民池的数据被清空。

五、编写智能合约

1. 合约分析

(1)合约分析

(2)核心方法

(3)辅助方法

 

2. 合约编写

(1)定义合约:定义合约属性、构造函数,设置管理员。

contract Lottery {
    address manager;  // 管理员
    address[] players;  // 投了注的彩民
    address winner;   // 上期彩票的胜出者
    uint256 round = 1;    // 第几期
    
    constructor() public {
        manager = msg.sender;
    }
}

(2)参与投注:把参与者的地址添加到players中。

// 投注
function play() public payable {
    // 限定投足金额为1eth
    require(msg.value == 1 ether);
    players.push(msg.sender);
}

(3)开奖

问题:如何确定中奖者?

解决办法:生成players的随机索引值。这里使用难度值,当前时间,参与人数作为种子生成一个大的数字,然后在对参与人数进行求余操作。使用余数作为随机索引值。

// 开奖
function kaiJIang() public {
    // 1.设置Winner
    // 生成随机下标
    bytes memory v1 = abi.encodePacked(block.difficulty, now, players.length);
    bytes32 v2 = keccak256(v1);
    uint v3 = uint256(v2) % players.length;
    winner = players[v3];
    // 2.把奖池的金额转账给winner
    winner.transfer(address(this).balance);
    // 3.清空plays
    delete players;
    // 4.期数加1
    round++;
}

(4)退奖:遍历players,逐一转账,并清除players。

// 退奖
function tuiJiang() public {
    require(players.length != 0);
    // 1.把奖池的金额退还给每一个玩
    for (uint i = 0; i < players.length; i++) {
        players[i].transfer(1 ether);
    }
    // 2.清空plays
    delete players;
    // 3.期数加1
    round++;
}

(5)定义辅助函数

// 获取奖金池的金额
function getAmount() public view returns(uint256) {
    return address(this).balance;
}
    
// 获取管理员地址
function getManagerAddress() public view returns(address) {
    return manager;
}
   
// 返回当前期数
function getRound() public view returns(uint256) {
    return round;
}
 
// 返回中奖者地址
function getWinner() public view returns(address) {
    return winner;
}
    
// 返回参与彩民的地址
function getPlays() public view returns(address[]) {
    return players;
}

(6)定义修饰器:非管理员不允许调用被修饰的函数

// 修饰器,限定只有管理员才有权操作
modifier onlyManager() {
    require(manager == msg.sender);
    _;
}

(7)在kaiJiang和tuiJiang方法定义中添加修饰器

// 开奖
function kaiJIang() public onlyManager {...}

// 退奖
function tuiJiang() public onlyManager {...}

最后,在remix上测试合约。

猜你喜欢

转载自blog.csdn.net/zhongliwen1981/article/details/90030336