-
Notifications
You must be signed in to change notification settings - Fork 1
/
miner.sol
173 lines (158 loc) · 6.15 KB
/
miner.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
pragma solidity ^0.5.0;
/**
* @author mlin-dxchain, bli-dxchain
* @title the base of the virtualminer game
*/
contract VirtualMiner {
address _owner;
constructor() public payable {
_owner = msg.sender;
}
struct Miner {
uint32 diskSpace;
uint minerId;
string minerName;
bool available;
}
struct User {
address userAddress;
string username;
mapping (uint => Miner) userMiners;
uint16 minerIndex;
uint8 minersInSmallPool;
uint8 minersInMedPool;
uint16 minersInLargePool;
}
/**
* @notice checks if they're the owner of the user
* @dev require the userId to match the sender's address
*/
modifier isOwnerOfUser(uint _userId) {
require(userToAddress[_userId] == msg.sender, "You're not the user!");
_;
}
/**
* @notice checks if they own that miner
*/
modifier isOwnerOfMiner(uint _minerId, uint _userId) {
require(minerToUser[_minerId] == _userId, "You do not own this miner!");
_;
}
/**
* @dev checks if you are the owner
*/
modifier onlyOwner() {
require(msg.sender == _owner, "You are not the owner.");
_;
}
/**
* @notice the array storing all the users.
* @dev users are identified by their index in this array.
*/
User[] public users;
string[] public minernames;
mapping (uint => address payable) userToAddress;
mapping (address => uint) addressToUser;
mapping (uint => uint) minerToUser;
mapping (uint => uint) minerIdToMinerIndex;
mapping (string => uint) minerNameToMinerId;
mapping(string => uint) userNameToUserId;
/**
* @notice creates a new user
* @dev stores user id into mapping
*/
function _createNewUser(string calldata _name) external {
require(usernameAvailability(_name), "Name is unavailable. Please try another.");
require(uniqueUser(msg.sender), "You already have an account!");
address payable userAddress = msg.sender;
uint id = users.push(User(msg.sender, _name, 0, 0, 0, 0)) - 1;
userToAddress[id] = userAddress;
addressToUser[userAddress] = id;
userNameToUserId[_name] = id;
}
uint minerCost = 9656297296172600;
uint upgradeCost = 10000000000000;
// creates a new miner
function _createNewMiner(string memory _minerName) internal {
require(minernameAvailability(_minerName), "Name is unavailable. Please try another.");
uint userId = addressToUser[msg.sender];
uint minerId = _minerIdGeneration(_minerName);
minerToUser[minerId] = userId;
minerIdToMinerIndex[minerId] = users[userId].minerIndex;
minerNameToMinerId[_minerName] = minerId;
minernames.push(_minerName);
users[userId].userMiners[users[userId].minerIndex] = Miner(32, minerId, _minerName, true);
users[userId].minerIndex++;
}
/**
* @param _minerName the name of the miner
* @notice purchases new miner
*/
function _purchaseMiner(string memory _minerName) public payable {
require(msg.value == minerCost, "Required amount is 9656297296172600 Wei");
_createNewMiner(_minerName);
}
/// @notice upgrades a miner
function _upgradeMiner(string calldata _username, string calldata _minername) external payable
isOwnerOfUser(userNameToUserId[_username])
isOwnerOfMiner(minerNameToMinerId[_minername], userNameToUserId[_username]) {
require(msg.value == upgradeCost, "Required amount is 10000000000000 Wei");
uint userId = userNameToUserId[_username];
uint minerId = minerNameToMinerId[_minername];
uint minerIndex = minerIdToMinerIndex[minerId];
require(users[userId].userMiners[minerIndex].diskSpace <= 1000000, "Your miner is fully upgraded!");
users[userId].userMiners[minerIndex].diskSpace += 32;
}
/// @notice creates a random minerId
uint randNonce = 0;
function _minerIdGeneration(string memory _minerName) private returns(uint) {
randNonce++;
return uint(keccak256(abi.encodePacked(now, randNonce, _minerName))) % (10 ** 16);
}
/// @return minerId from minerName
function getMinerId(string memory _minerName) public view returns (uint minerId) {
minerId = minerNameToMinerId[_minerName];
}
/// @return minerDiskSpace
function getMinerDiskspace(string memory _minerName) public view returns (uint minerDiskSpace) {
uint minerId = getMinerId(_minerName);
uint userId = minerToUser[minerId];
uint minerIndex = minerIdToMinerIndex[minerId];
minerDiskSpace = users[userId].userMiners[minerIndex].diskSpace;
}
/// @return deploy cost of miner
function getMinerDeployCost(string calldata _minerName) external view returns (uint deployCost) {
uint minerId = getMinerId(_minerName);
uint userId = minerToUser[minerId];
uint minerIndex = minerIdToMinerIndex[minerId];
deployCost = 4828148648086300 + (100000000000 * users[userId].userMiners[minerIndex].diskSpace);
}
/// @return true of minername is available
function minernameAvailability(string memory minername) internal view returns (bool) {
for (uint i = 0; i < minernames.length; i++) {
if (keccak256(abi.encodePacked(minername)) == keccak256(abi.encodePacked(minernames[i]))) {
return false;
}
}
return true;
}
/// @return true of username is available
function usernameAvailability(string memory username) internal view returns (bool) {
for (uint i = 0; i < users.length; i++) {
uint userId = userNameToUserId[username];
if (keccak256(abi.encodePacked(users[userId].username)) == keccak256(abi.encodePacked(username))) {
return false;
}
}
return true;
}
/// @return true if there is no account linked to that address
function uniqueUser(address userAddress) internal view returns (bool) {
for (uint i = 0; i < users.length; i++) {
if (userAddress == users[i].userAddress) {
return false;
}
}
return true;
}
}