-
Notifications
You must be signed in to change notification settings - Fork 0
/
Tiles.sol
101 lines (86 loc) · 3.24 KB
/
Tiles.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
interface IERC20 {
function transferFrom(address sender, address recepient, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
}
contract Tiles {
bool public paused = false;
uint32 public immutable width;
uint32 public immutable height;
address private immutable owner;
IERC20 private immutable pay_token;
event ChangePixel(
address indexed _painter,
uint32[2] indexed _coords,
uint32 _color,
uint256 _paid_amount
);
struct Pixel {
uint32 color;
address painter;
uint256 paid_amount;
}
mapping(uint32 => mapping(uint32 => Pixel)) public pixels;
constructor(address token, uint32 max_width, uint32 max_height) {
owner = msg.sender;
width = max_width;
height = max_height;
pay_token = IERC20(token);
}
modifier ownerOnly() {
require(msg.sender == owner, "Not authorized, must be owner");
_;
}
//setting pixel
function setPixel(uint256 amount, uint32 x, uint32 y, uint32 color) public {
//don't allow if paused
require(!paused, "Coloring is paused");
//make sure is within dimensions
require(width > x, "x too large, outside dimensions");
require(height > y, "y too large, outside dimensions");
//amount must be at least 1 XAC
require(1000000000000000000 <= amount, "Amount paid must be at least 1 token");
//check if amount is more than current amount (this also disallows paying 0 for pixel)
require(pixels[y][x].paid_amount < amount, "Amount not enough");
//try to send
//caller must first call approve with the token and this contract
bool send_success = pay_token.transferFrom(msg.sender, address(this), amount);
require(send_success, "Failed to send");
//change pixel
pixels[y][x] = Pixel(color, msg.sender, amount);
//emit event
emit ChangePixel(msg.sender, [x, y], color, amount);
}
function setPixelBatch(uint256[] calldata amounts, uint32[] calldata xs, uint32[] calldata ys, uint32[] calldata colors) public {
//make sure all are same length
require(amounts.length == xs.length && xs.length == ys.length && ys.length == colors.length, "All arrays must be same length");
for (uint i = 0; i < amounts.length; i++) {
setPixel(amounts[i], xs[i], ys[i], colors[i]);
}
}
//admin functions
function clearPixel(uint32 x, uint32 y) public ownerOnly {
//allow clearing even if paused
//make sure is within dimensions
require(width > x, "x too large, outside dimensions");
require(height > y, "y too large, outside dimensions");
//actually remove
delete pixels[y][x];
}
function pause() external ownerOnly returns (bool) {
require(!paused, "Painting is already paused");
paused = true;
return paused;
}
function unpause() external ownerOnly returns (bool) {
require(paused, "Painting is already unpaused");
paused = false;
return paused;
}
function withdraw(uint256 amount) external ownerOnly returns (bool) {
bool send_success = pay_token.transfer(owner, amount);
require(send_success, "Failed to send");
return true;
}
}