-
Notifications
You must be signed in to change notification settings - Fork 1
/
MixAccountItems.sol
170 lines (149 loc) · 5.51 KB
/
MixAccountItems.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
pragma solidity ^0.5.12;
import "mix-item-store/MixItemStoreRegistry.sol";
/**
* @title MixAccountItems
* @author Jonathan Brown <jbrown@mix-blockchain.org>
* @dev Enables users to attach a list of items to their account.
*/
contract MixAccountItems {
/**
* @dev Mapping of account to array of itemIds.
*/
mapping (address => bytes32[]) accountItemIds;
/**
* @dev Mapping of account to mapping of itemId to index + 1 in accountItemIds.
*/
mapping (address => mapping(bytes32 => uint)) accountItemIdIndex;
/**
* @dev MixItemStoreRegistry contract.
*/
MixItemStoreRegistry public itemStoreRegistry;
/**
* @dev An account has added an item.
* @param account Account that has added an item.
* @param itemId itemId of item that has been added.
*/
event AddItem(address indexed account, bytes32 indexed itemId);
/**
* @dev An account has removed an item.
* @param account Account that has removed an item.
* @param itemId itemId of item that has been removed.
*/
event RemoveItem(address indexed account, bytes32 indexed itemId);
/**
* @dev Revert if the item is not in sender's list.
* @param itemId itemId that must be in the list.
*/
modifier isAdded(bytes32 itemId) {
require (accountItemIdIndex[msg.sender][itemId] > 0, "Item has not been added.");
_;
}
/**
* @dev Revert if the item is in sender's list.
* @param itemId itemId that must not be in the list.
*/
modifier isNotAdded(bytes32 itemId) {
require (accountItemIdIndex[msg.sender][itemId] == 0, "Item has already been added.");
_;
}
/**
* @dev Revert if the item is not owned by sender.
* @param itemId itemId that must be owned.
*/
modifier isOwner(bytes32 itemId) {
require (itemStoreRegistry.getItemStore(itemId).getOwner(itemId) == msg.sender, "Item is not owned by sender.");
_;
}
/**
* @param _itemStoreRegistry Address of the MixItemStoreRegistry contract.
*/
constructor(MixItemStoreRegistry _itemStoreRegistry) public {
// Store the address of the MixItemStoreRegistry contract.
itemStoreRegistry = _itemStoreRegistry;
}
/**
* @dev Add an item to the user.
* @param itemId itemId of item to be added.
*/
function addItem(bytes32 itemId) external isNotAdded(itemId) isOwner(itemId) {
// Get the list of itemIds for sender.
bytes32[] storage itemIds = accountItemIds[msg.sender];
// Add the itemId to the list.
itemIds.push(itemId);
// Record the index + 1.
accountItemIdIndex[msg.sender][itemId] = itemIds.length;
// Log the adding of the item.
emit AddItem(msg.sender, itemId);
}
/**
* @dev Remove an item from the user.
* @param itemId itemId of item to be removed.
*/
function removeItem(bytes32 itemId) external isAdded(itemId) isOwner(itemId) {
// Get the list of itemIds for sender.
bytes32[] storage itemIds = accountItemIds[msg.sender];
// Get the mapping of itemId indexes for sender.
mapping(bytes32 => uint) storage itemIdIndex = accountItemIdIndex[msg.sender];
// Get the index + 1 of the itemId to be removed and delete it from state.
uint i = itemIdIndex[itemId];
delete itemIdIndex[itemId];
// Check if this is not the last itemId.
if (i != itemIds.length) {
// Overwrite the itemId with the last itemId.
bytes32 itemIdMoving = itemIds[itemIds.length - 1];
itemIds[i - 1] = itemIdMoving;
itemIdIndex[itemIdMoving] = i;
}
// Remove the last itemId.
itemIds.pop();
// Log the removing of the item.
emit RemoveItem(msg.sender, itemId);
}
/**
* @dev Check if a specific item is in sender's list.
* @param itemId itemId of item to check for.
* @return True if item exists in sender's list.
*/
function getItemExists(bytes32 itemId) external view returns (bool) {
return accountItemIdIndex[msg.sender][itemId] > 0;
}
/**
* @dev Get number of items in sender's list.
* @return Number of items in sender's list.
*/
function getItemCount() external view returns (uint) {
return accountItemIds[msg.sender].length;
}
/**
* @dev Get all items in sender's list.
* @return All items in sender's list.
*/
function getAllItems() external view returns (bytes32[] memory) {
return accountItemIds[msg.sender];
}
/**
* @dev Check if a specific item is in account's list.
* @param account Account to check for item.
* @param itemId itemId of item to check for.
* @return True if item exists in sender's list.
*/
function getItemExistsByAccount(address account, bytes32 itemId) external view returns (bool) {
return accountItemIdIndex[account][itemId] > 0;
}
/**
* @dev Get number of items in account's list.
* @param account Account to get item count of.
* @return Number of items in account's list.
*/
function getItemCountByAccount(address account) external view returns (uint) {
return accountItemIds[account].length;
}
/**
* @dev Get all items in account's list.
* @param account Account to get items of.
* @return All items in account's list.
*/
function getAllItemsByAccount(address account) external view returns (bytes32[] memory) {
return accountItemIds[account];
}
}