-
Notifications
You must be signed in to change notification settings - Fork 0
/
contract.sol
193 lines (165 loc) · 7.62 KB
/
contract.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//SPDX-License-Identifier: Unlicensed
pragma solidity >=0.6.0 <0.9.0;
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() public {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
contract Predict is ReentrancyGuard {
address public admin;
uint256 public minBetAmount;
uint256 public treasuryFee;
uint256 public treasuryAmount;
uint256 public currentRound;
uint256 public MAX_TREASURY_FEE = 10;
event ClaimReward(address claimer, uint256 rewardAmount);
event PredictionMade(address predictor, uint256 amountBet, bool bull_predicted);
constructor(uint256 _minBetAmount, uint256 _treasuryFee) public {
admin = msg.sender;
minBetAmount = _minBetAmount;
treasuryFee = _treasuryFee;
currentRound = 0;
}
modifier onlyAdmin() {
require(msg.sender == admin, "Only admin is allowed!");
_;
}
struct Round {
uint256 startTime;
uint256 closeTime;
uint256 totalAmount;
uint256 bullAmount;
uint256 bearAmount;
uint256 startPrice;
uint256 closePrice;
bool bull_won;
mapping(address => bool) predicted;
mapping(address => bool) bull_predicted;
mapping(address => uint256) betted_amount;
mapping(address => bool) claimed_reward;
}
mapping(uint => Round) rounds;
function getPredicted() external view returns(bool) {
return rounds[currentRound - 1].predicted[msg.sender];
}
function claimTreasury() external onlyAdmin {
require(treasuryAmount > 0, "The treasury must not be empty");
payable(admin).transfer(address(this).balance);
treasuryAmount = 0;
}
function setTreasuryFee(uint256 _treasuryFee) external onlyAdmin {
require(_treasuryFee <= MAX_TREASURY_FEE, "Treasury fee cannot exceed 10%");
treasuryFee = _treasuryFee;
}
function setMinBetAmount(uint256 _minBetAmount) external onlyAdmin {
minBetAmount = _minBetAmount;
}
function bullBet() external payable nonReentrant {
require(msg.value >= minBetAmount, "Bet amount must be greater than minBetAmount");
require(rounds[currentRound - 1].predicted[msg.sender] == false, "Already predicted for this round");
require(block.timestamp < rounds[currentRound - 1].closeTime, "Round is closed");
rounds[currentRound - 1].totalAmount += (msg.value * (100 - treasuryFee) / 100);
rounds[currentRound - 1].bullAmount += (msg.value * (100 - treasuryFee) / 100);
treasuryAmount += (msg.value * treasuryFee) / 100;
rounds[currentRound - 1].predicted[msg.sender] = true;
rounds[currentRound - 1].bull_predicted[msg.sender] = true;
rounds[currentRound - 1].betted_amount[msg.sender] = msg.value * (100 - treasuryFee) / 100;
emit PredictionMade(msg.sender, msg.value, true);
}
function bearBet() external payable nonReentrant {
require(msg.value >= minBetAmount, "Bet amount must be greater than minBetAmount");
require(rounds[currentRound - 1].predicted[msg.sender] == false, "Already predicted for this round");
require(block.timestamp < rounds[currentRound - 1].closeTime, "Round is closed");
rounds[currentRound - 1].totalAmount += (msg.value * (100 - treasuryFee) / 100);
rounds[currentRound - 1].bearAmount += (msg.value * (100 - treasuryFee) / 100);
treasuryAmount += (msg.value * treasuryFee) / 100;
rounds[currentRound - 1].predicted[msg.sender] = true;
rounds[currentRound - 1].bull_predicted[msg.sender] = false;
rounds[currentRound - 1].betted_amount[msg.sender] = msg.value * (100 - treasuryFee) / 100;
emit PredictionMade(msg.sender, msg.value, false);
}
function claimReward() external nonReentrant {
require(block.timestamp >= rounds[currentRound - 1].closeTime, "The round has to be finished before claiming reward");
require(rounds[currentRound - 1].bull_predicted[msg.sender] == rounds[currentRound - 1].bull_won, "You didn't win the round");
require(rounds[currentRound - 1].claimed_reward[msg.sender] == false, "You already claimed your reward");
uint256 reward;
if (rounds[currentRound - 1].bull_won) {
reward = rounds[currentRound - 1].betted_amount[msg.sender] * rounds[currentRound - 1].totalAmount / rounds[currentRound - 1].bullAmount;
} else {
reward = rounds[currentRound - 1].betted_amount[msg.sender] * rounds[currentRound - 1].totalAmount / rounds[currentRound - 1].bearAmount;
}
msg.sender.transfer(reward);
emit ClaimReward(msg.sender, reward);
rounds[currentRound - 1].claimed_reward[msg.sender] = true;
}
function setWinningSide() external nonReentrant onlyAdmin {
require(block.timestamp >= rounds[currentRound - 1].closeTime, "The round has to be finished to set the winning side");
rounds[currentRound - 1].closePrice = getPrice();
if (rounds[currentRound - 1].startPrice < rounds[currentRound - 1].closePrice) {
rounds[currentRound - 1].bull_won = true;
} else {
rounds[currentRound - 1].bull_won = false;
}
}
function getWinningSide() external view returns(bool) {
return rounds[currentRound - 1].bull_won;
}
function createRound() external onlyAdmin() nonReentrant {
Round storage round = rounds[currentRound];
round.startTime = block.timestamp;
round.closeTime = block.timestamp + 1 minutes;
round.totalAmount = 0;
round.bullAmount = 0;
round.bearAmount = 0;
round.startPrice = getPrice();
currentRound = currentRound + 1;
}
function getUpPayout() external view returns(uint256) {
uint256 payout = rounds[currentRound - 1].totalAmount / rounds[currentRound - 1].bullAmount;
if (payout != 0) {
return payout;
}
}
function getDownPayout() external view returns(uint256) {
uint256 payout = rounds[currentRound - 1].totalAmount / rounds[currentRound - 1].bearAmount;
if (payout != 0) {
return payout;
}
}
function getPrizePool() external view returns(uint256) {
return rounds[currentRound - 1].totalAmount;
}
function getClosingTime() external view returns(uint256) {
return rounds[currentRound - 1].closeTime;
}
function getCurrentTime() external view returns(uint256) {
return now;
}
//Functions relating to the price oracles
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0xECe365B379E1dD183B20fc5f022230C044d51404);
return priceFeed.version();
}
function getPrice() public view returns(uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0xECe365B379E1dD183B20fc5f022230C044d51404);
(,int256 answer,,,) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversation rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}