-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNFTLottery.sol
149 lines (117 loc) · 4.56 KB
/
NFTLottery.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "./interface/INFTLottery.sol";
contract NFTLottery is INFTLottery {
address public owner;
address[] internal mWinners;
uint256 public ticketPrice;
uint256 internal mLotteryNumber;
uint256 internal mWinningPercentage;
address mParentAddress;
bool public ended;
address[] public mPlayers;
mapping(address => bool) internal mParticipants;
uint256 internal prize = 0;
IERC721 private _nftContract;
bool private _nftRequired;
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can call this function");
_;
}
modifier onlyWinner(){
require(addressIsInWinnerList() == true , "You not in this lottery winners list!");
require(prize != 0 , "Lottery has not finished yet!");
_;
}
function addressIsInWinnerList() private view returns (bool) {
for (uint i = 0; i < mWinners.length; i++) {
if (mWinners[i] == msg.sender) {
return true;
}
}
return false;
}
constructor(
address lotteryOwner,
uint256 _ticketPrice,
IERC721 nftContract,
bool nftRequired,
uint256 winningPercentage,
address parentAddress
) {
require(winningPercentage > 0 && winningPercentage <= 100, "Winning percentage must be between 1 and 100");
owner = lotteryOwner;
ticketPrice = _ticketPrice;
_nftContract = nftContract;
_nftRequired = nftRequired;
mWinningPercentage = winningPercentage;
mParentAddress = parentAddress;
}
function enterLottery() external payable override {
require(!ended, "Lottery has already ended");
require(msg.value == ticketPrice, "Incorrect ticket price");
require(!mParticipants[msg.sender], "You have already purchased a ticket");
if (_nftRequired) {
require(_nftContract.balanceOf(msg.sender) > 0, "You must own an NFT from the designated collection to participate");
}
mParticipants[msg.sender] = true;
mPlayers.push(msg.sender);
}
function pickWinner() external override onlyOwner {
require(!ended, "Lottery has already ended");
uint256 balance = address(this).balance;
require(balance > 0, "No funds to distribute as prize");
ended = true;
mLotteryNumber = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, mPlayers.length)));
uint256 numWinners = (mPlayers.length * mWinningPercentage) / 100;
uint256[] memory indices = randomIndices(numWinners, mPlayers.length);
for (uint256 i = 0; i < numWinners; i++) {
mWinners.push(mPlayers[indices[i]]);
}
prize = balance / numWinners;
emit LotteryEnded(mWinners, prize);
}
function getPlayers() external view returns(address[] memory) {
return mPlayers;
}
function getCondition(address participant) external view override returns(bool) {
if (_nftRequired) {
return _nftContract.balanceOf(participant) > 0;
} else {
// Add any other condition here
return true;
}
}
function getWinners() external view override returns(address[] memory) {
require(ended, "Lottery has not ended yet");
return mWinners;
}
function getLotteryNumber() external view override returns(uint256) {
require(ended, "Lottery has not ended yet");
return mLotteryNumber;
}
function nftContract() external view override returns(IERC721) {
return _nftContract;
}
function getParticipants(address participant) external view override returns(bool) {
return mParticipants[participant];
}
function randomIndices(uint256 numWinners, uint256 ticketCount) private view returns (uint256[] memory) {
uint256[] memory indices = new uint256[](ticketCount);
for (uint256 i = 0; i < ticketCount; i++) {
indices[i] = i;
}
for (uint256 i = 0; i < numWinners; i++) {
uint256 j = i + uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, i))) % (ticketCount - i);
(indices[i], indices[j]) = (indices[j], indices[i]);
}
return indices;
}
function getWinningPercentage() external view override returns(uint){
return mWinningPercentage;
}
function claimPrize() external override onlyWinner {
payable(msg.sender).transfer(prize);
}
}