-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathArcade.sol
114 lines (92 loc) · 3.63 KB
/
Arcade.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// A new Arcade is online.
// Let's see who can win over 200 PRIZE tokens.
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";
import {ERC20, IERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {Base} from "../Base.sol";
contract Arcade is ERC20("prize", "PRIZE"), Ownable {
address public currentPlayer;
address[] public players;
uint256 public numPlayers;
uint256 public lastEarnTimestamp;
mapping(address player => uint256 points) public scoreboard;
event PlayerEarned(address indexed player, uint256 currentPoints);
event PlayerChanged(address indexed oldPlayer, address indexed newPlayer);
modifier onlyPlayer() {
require(msg.sender == currentPlayer, "Unauthorized");
_;
}
constructor(address player) {
currentPlayer = player;
}
function getCurrentPlayerPoints() public view returns (uint256) {
return scoreboard[currentPlayer];
}
function isActivePlayer(address player) public view returns (bool) {
for (uint256 i; i < numPlayers; ++i) {
if (players[i] == player) {
return true;
}
}
return false;
}
function setPoints(address player, uint256 points) external onlyOwner {
scoreboard[player] = points;
if (!isActivePlayer(player)) {
players.push(player);
numPlayers++;
}
}
/// @notice Earn 10 points at most once per 10 minutes
function earn() external onlyPlayer {
require(block.timestamp >= lastEarnTimestamp + 10 minutes, "Too frequent");
address player = msg.sender;
scoreboard[player] += 10;
lastEarnTimestamp = block.timestamp;
emit PlayerEarned(player, getCurrentPlayerPoints());
}
/// @notice Be cautious as you might lose the ability to earn and redeem points afterward
function changePlayer(address newPlayer) external onlyPlayer {
address oldPlayer = currentPlayer;
emit PlayerChanged(_redeem(oldPlayer), _setNewPlayer(newPlayer));
}
/// @notice Redeem points for minting PRIZE tokens at 1:1 ratio
function redeem() external onlyPlayer {
_redeem(msg.sender);
}
function _redeem(address player) internal returns (address) {
uint256 points = getCurrentPlayerPoints();
_mint(player, points);
delete scoreboard[player];
return player;
}
function _setNewPlayer(address newPlayer) internal returns (address) {
currentPlayer = newPlayer;
return newPlayer;
}
}
contract ArcadeBase is Base {
address public constant player1 = 0x1111Ad317502Ba53c84BD2D859237D33846Ca2e7;
address public constant player2 = 0x2222140D9A0809B35D88636E3dDeC37B6bDd7CB2;
address public constant player3 = 0x33339741B46D6EE8adCc0d796dE2aB6Ea3E8dc2A;
address public constant player4 = 0x4444bd21FA6Ec8846308e926B86D06b74f63f4aD;
Arcade public arcade;
address public you;
constructor(uint256 startTime, uint256 endTime, uint256 fullScore) Base(startTime, endTime, fullScore) {}
function setup() external override {
arcade = new Arcade(msg.sender);
you = msg.sender;
// Set initial points for players
arcade.setPoints(you, 0);
arcade.setPoints(player1, 80);
arcade.setPoints(player2, 120);
arcade.setPoints(player3, 180);
arcade.setPoints(player4, 190);
}
/// @notice Do you have 200 PRIZE?
function solve() public override {
require(IERC20(arcade).balanceOf(you) >= 200, "Unsolved");
super.solve();
}
}