1
1
// SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.24 ;
2
+ pragma solidity 0.8.26 ;
3
3
4
4
import "@openzeppelin/contracts/security/ReentrancyGuard.sol " ;
5
5
import "@openzeppelin/contracts/access/Ownable.sol " ;
6
6
7
7
contract AgentTrumpGame is ReentrancyGuard , Ownable {
8
- // State variables remain the same
9
8
uint256 public gameEndTime;
10
9
uint256 public constant INITIAL_GAME_DURATION = 30 minutes ;
11
10
uint256 public constant ESCALATION_PERIOD = 5 minutes ;
@@ -28,7 +27,6 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
28
27
29
28
mapping (address => PlayerResponse[]) public playerResponses;
30
29
31
- // Events remain the same
32
30
event GuessSubmitted (
33
31
address indexed player ,
34
32
uint256 amount ,
@@ -42,45 +40,44 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
42
40
event EscalationStarted (uint256 startTime );
43
41
event GameExtended (uint256 newEndTime , uint256 newMultiplier );
44
42
45
- // Constructor and other functions remain the same until endGame
46
43
constructor () Ownable (msg .sender ) {
47
44
gameEndTime = block .timestamp + INITIAL_GAME_DURATION;
48
45
currentMultiplier = 100 ;
49
46
lastGuessTime = block .timestamp ;
50
47
currentRequiredAmount = GAME_FEE;
51
48
}
52
49
53
- // Modified endGame function
54
50
function endGame () external onlyOwner nonReentrant {
55
51
require (totalCollected > 0 , "No funds to distribute " );
56
52
require (lastPlayer != address (0 ), "No players participated " );
57
53
58
- uint256 lastPlayerReward = (totalCollected * 10 ) / 100 ;
59
- uint256 ownerReward = totalCollected - lastPlayerReward;
54
+ uint256 ownerReward;
55
+ uint256 lastPlayerReward;
56
+
57
+ if (block .timestamp >= gameEndTime) {
58
+ lastPlayerReward = (totalCollected * 10 ) / 100 ;
59
+ ownerReward = totalCollected - lastPlayerReward;
60
+
61
+ (bool success1 , ) = payable (lastPlayer).call {value: lastPlayerReward}("" );
62
+ require (success1, "Last player reward transfer failed " );
63
+ } else {
64
+ ownerReward = totalCollected;
65
+ }
60
66
61
67
totalCollected = 0 ;
62
68
63
- (bool success1 , ) = payable (lastPlayer).call {value: lastPlayerReward}("" );
64
- require (success1, "Last player reward transfer failed " );
65
-
66
69
(bool success2 , ) = payable (owner ()).call {value: ownerReward}("" );
67
70
require (success2, "Owner reward transfer failed " );
68
71
69
- // Update game state
70
72
gameEndTime = block .timestamp ;
71
73
gameWon = false ;
72
74
73
75
emit GameEnded (lastPlayer, lastPlayerReward, ownerReward);
74
76
}
75
77
76
- // Rest of the contract functions remain unchanged
77
- function deposit () external payable onlyOwner {
78
- require (msg .value > 0 , "Must deposit some ETH " );
79
- }
80
-
81
78
function withdraw () external onlyOwner {
82
- require (block .timestamp > gameEndTime || gameWon, "Game still in progress " );
83
79
require (address (this ).balance > 0 , "No balance to withdraw " );
80
+ require (totalCollected == 0 , "Must call endGame first to distribute rewards " );
84
81
85
82
(bool success , ) = payable (owner ()).call {value: address (this ).balance}("" );
86
83
require (success, "Withdraw failed " );
@@ -107,30 +104,46 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
107
104
require (bytes (response).length > 0 , "Response cannot be empty " );
108
105
require (bytes (response).length <= 1000 , "Response too long " );
109
106
107
+ bytes memory responseBytes = bytes (response);
108
+ for (uint i = 0 ; i < responseBytes.length ; i++ ) {
109
+ require (
110
+ // Basic printable ASCII (includes letters, numbers, basic punctuation)
111
+ (responseBytes[i] >= 0x20 && responseBytes[i] <= 0x7E ) ||
112
+ // Additional special characters
113
+ responseBytes[i] == 0x2C || // comma
114
+ responseBytes[i] == 0x3B || // semicolon
115
+ responseBytes[i] == 0x22 || // double quote "
116
+ responseBytes[i] == 0x27 || // single quote/apostrophe '
117
+ // You can add more special characters here if needed
118
+ false ,
119
+ "Invalid character in response "
120
+ );
121
+ }
122
+
123
+ // Rest of the function remains unchanged
124
+ uint256 requiredAmount = getCurrentRequiredAmount ();
125
+ require (msg .value >= requiredAmount, "Insufficient payment " );
126
+
110
127
if (shouldStartEscalation ()) {
111
128
escalationActive = true ;
112
129
escalationStartTime = block .timestamp ;
113
130
currentRequiredAmount = GAME_FEE * BASE_MULTIPLIER / 100 ;
114
131
emit EscalationStarted (escalationStartTime);
115
132
}
116
-
117
- require (msg .value >= currentRequiredAmount, "Insufficient payment " );
118
133
119
134
if (shouldExtendGame ()) {
120
135
gameEndTime = block .timestamp + ESCALATION_PERIOD;
121
136
currentRequiredAmount = currentRequiredAmount * BASE_MULTIPLIER / 100 ;
122
137
emit GameExtended (gameEndTime, currentRequiredAmount);
123
138
}
124
139
125
- require (block .timestamp <= gameEndTime, "Game has ended " );
126
-
127
- if (msg .value > currentRequiredAmount) {
128
- uint256 excess = msg .value - currentRequiredAmount;
140
+ if (msg .value > requiredAmount) {
141
+ uint256 excess = msg .value - requiredAmount;
129
142
(bool success , ) = payable (msg .sender ).call {value: excess}("" );
130
143
require (success, "Refund failed " );
131
144
}
132
145
133
- uint256 ownerShare = (currentRequiredAmount * 30 ) / 100 ;
146
+ uint256 ownerShare = (requiredAmount * 30 ) / 100 ;
134
147
(bool success2 , ) = payable (owner ()).call {value: ownerShare}("" );
135
148
require (success2, "Owner payment failed " );
136
149
@@ -142,25 +155,25 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
142
155
143
156
uint256 responseIndex = playerResponses[msg .sender ].length - 1 ;
144
157
145
- totalCollected += (currentRequiredAmount - ownerShare);
158
+ totalCollected += (requiredAmount - ownerShare);
146
159
lastPlayer = msg .sender ;
147
160
lastGuessTime = block .timestamp ;
148
161
149
162
emit GuessSubmitted (
150
163
msg .sender ,
151
- currentRequiredAmount ,
164
+ requiredAmount ,
152
165
currentMultiplier,
153
166
response,
154
167
block .timestamp ,
155
168
responseIndex
156
169
);
157
170
}
158
171
159
- function getPlayerResponseCount (address player ) external view returns (uint256 ) {
172
+ function getPlayerResponseCount (address player ) public view returns (uint256 ) {
160
173
return playerResponses[player].length ;
161
174
}
162
175
163
- function getPlayerResponseByIndex (address player , uint256 index ) external view returns (
176
+ function getPlayerResponseByIndex (address player , uint256 index ) public view returns (
164
177
string memory response ,
165
178
uint256 timestamp ,
166
179
bool exists
@@ -170,7 +183,7 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
170
183
return (playerResponse.response, playerResponse.timestamp, playerResponse.exists);
171
184
}
172
185
173
- function getAllPlayerResponses (address player ) external view returns (
186
+ function getAllPlayerResponses (address player ) public view returns (
174
187
string [] memory responses ,
175
188
uint256 [] memory timestamps ,
176
189
bool [] memory exists
@@ -192,7 +205,6 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
192
205
}
193
206
194
207
function buttonPushed (address winner ) external onlyOwner nonReentrant {
195
- require (block .timestamp <= gameEndTime, "Game has ended " );
196
208
require (! gameWon, "Game already won " );
197
209
require (winner != address (0 ), "Invalid winner address " );
198
210
require (playerResponses[winner].length > 0 , "Winner must have submitted at least one response " );
@@ -207,20 +219,24 @@ contract AgentTrumpGame is ReentrancyGuard, Ownable {
207
219
emit GameWon (winner, reward);
208
220
}
209
221
210
- function getTimeRemaining () external view returns (uint256 ) {
222
+ function getTimeRemaining () public view returns (uint256 ) {
211
223
if (block .timestamp >= gameEndTime) return 0 ;
212
224
return gameEndTime - block .timestamp ;
213
225
}
214
226
215
- function getContractBalance () external view returns (uint256 ) {
227
+ function getContractBalance () public view returns (uint256 ) {
216
228
return address (this ).balance;
217
229
}
218
230
219
- function getCurrentEscalationPeriod () external view returns (uint256 ) {
231
+ function getCurrentEscalationPeriod () public view returns (uint256 ) {
220
232
if (! escalationActive) return 0 ;
221
233
return (block .timestamp - escalationStartTime) / ESCALATION_PERIOD;
222
234
}
223
235
236
+ function deposit () external payable onlyOwner {
237
+ require (msg .value > 0 , "Must deposit some ETH " );
238
+ }
239
+
224
240
receive () external payable {}
225
241
fallback () external payable {}
226
242
}
0 commit comments