Solidity:使用映射和代码设计彩票合同地址



我正在写彩票合同。由于气体成本很高,我想使用映射而不是数组,并且我在struct中定义了id。然而,我无法摆脱代码结构。如何确定获胜者以及如何清空获胜者之后的通讯簿。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract freeLottery {
address public owner;
uint public lotteryId;
mapping (uint => address payable) public lotteryHistory;

struct Players {
bool isWinner;
uint id;
}

mapping (address => Players) players;
uint playersCount=0;

constructor() {
owner = msg.sender;
lotteryId = 1;
}

function getWinner(uint lottery) public view returns (address payable) {
return lotteryHistory[lottery];
}

function getBalance() public view returns (uint) {
return address(this).balance;
}

function enter() public payable {        
players[msg.sender];
playersCount++;    
}               



function contribute() public payable onlyowner{
require(msg.value>0,"Please send an amount greater than 0");
}       

function getRandomNumber() internal view returns (uint) {
return uint(keccak256(abi.encodePacked(owner, block.timestamp)));
}

function pickWinner() public onlyowner {
require(address(this).balance>0,"Please upload balance");
uint index = getRandomNumber() % ???;
???

???

lotteryHistory[lotteryId] = players[id];
lotteryId++;

// reset the state of the contract
???;
}

modifier onlyowner() {
require(msg.sender == owner);
_;
}
}   

您不需要Players结构。在lotteryHistory中,您已经在跟踪获胜者地址。这样定义players映射:

// this will take care of storing in mapping instead of array
mapping (uint => address) players;
uint playersCount=0;

则在enter函数中:

function enter() public payable {    
// initially playersCount is 0. so increase it first  
playersCount++;
// payable vs normal address has different methods. for storing it wont matter  
players[playersCount]=payable(msg.sender);       
}               

pickWinner:

function pickWinner() public onlyowner returns (address payable) {
require(address(this).balance>0,"Please upload balance");
uint index = getRandomNumber() % playersCount;
address payable winner=payable(players[index]);

lotteryHistory[lotteryId] = winner;
// since you inialized lotteryId=1 in constructor
lotteryId++;

// for resetting, you have to do for loop
for (uint i=0; i< playersCount ; i++) {
delete players[i];
}     
return winner   ;   
}

我们可以使用lotteryId作为键,将players映射定义为嵌套映射,而不是执行for循环删除播放器。我们的地图将像这个

lotteryId => playersCount => address

所以在第一次彩票中,你会有

1 => playersCount => address

pickWinner中,您已经增加了lotteryId++。第一次抽奖后,您将开始一个新的映射

2 => playersCount => address

另外,在pickWinner中,选择获胜者后,您应该重置playersCount=0,您的enter功能将如下所示:

function enter() public payable {    
// initially playersCount is 0. so increase it first  
playersCount++;
// payable vs normal address has different methods. for storing it wont matter  
players[lotteryId][playersCount]=msg.sender;       
}         

相关内容

  • 没有找到相关文章

最新更新