-
Notifications
You must be signed in to change notification settings - Fork 28
/
ShifterRegistry.sol
182 lines (149 loc) · 6.94 KB
/
ShifterRegistry.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
174
175
176
177
178
179
180
181
182
pragma solidity ^0.5.8;
import "../libraries/Claimable.sol";
import "./ERC20Shifted.sol";
import "../libraries/LinkedList.sol";
import "./IShifter.sol";
/// @notice ShifterRegistry is a mapping from assets to their associated
/// ERC20Shifted and Shifter contracts.
contract ShifterRegistry is Claimable {
/// @dev The symbol is included twice because strings have to be hashed
/// first in order to be used as a log index/topic.
event LogShifterRegistered(string _symbol, string indexed _indexedSymbol, address indexed _tokenAddress, address indexed _shifterAddress);
event LogShifterDeregistered(string _symbol, string indexed _indexedSymbol, address indexed _tokenAddress, address indexed _shifterAddress);
event LogShifterUpdated(address indexed _tokenAddress, address indexed _currentShifterAddress, address indexed _newShifterAddress);
/// @notice The number of shifters registered
uint256 numShifters = 0;
/// @notice A list of shifter contracts
LinkedList.List private shifterList;
/// @notice A list of shifted token contracts
LinkedList.List private shiftedTokenList;
/// @notice A map of token addresses to canonical shifter addresses
mapping (address=>address) private shifterByToken;
/// @notice A map of token symbols to canonical shifter addresses
mapping (string=>address) private tokenBySymbol;
/// @notice Allow the owner to set the shifter address for a given
/// ERC20Shifted token contract.
///
/// @param _tokenAddress The address of the ERC20Shifted token contract.
/// @param _shifterAddress The address of the Shifter contract.
function setShifter(address _tokenAddress, address _shifterAddress) external onlyOwner {
// Check that token, shifter and symbol haven't already been registered
require(!LinkedList.isInList(shifterList, _shifterAddress), "shifter already registered");
require(shifterByToken[_tokenAddress] == address(0x0), "token already registered");
string memory symbol = ERC20Shifted(_tokenAddress).symbol();
require(tokenBySymbol[symbol] == address(0x0), "symbol already registered");
// Add to list of shifters
LinkedList.append(shifterList, _shifterAddress);
// Add to list of shifted tokens
LinkedList.append(shiftedTokenList, _tokenAddress);
tokenBySymbol[symbol] = _tokenAddress;
shifterByToken[_tokenAddress] = _shifterAddress;
numShifters += 1;
emit LogShifterRegistered(symbol, symbol, _tokenAddress, _shifterAddress);
}
/// @notice Allow the owner to update the shifter address for a given
/// ERC20Shifted token contract.
///
/// @param _tokenAddress The address of the ERC20Shifted token contract.
/// @param _newShifterAddress The updated address of the Shifter contract.
function updateShifter(address _tokenAddress, address _newShifterAddress) external onlyOwner {
// Check that token, shifter are registered
address currentShifter = shifterByToken[_tokenAddress];
require(shifterByToken[_tokenAddress] != address(0x0), "token not registered");
// Remove to list of shifters
LinkedList.remove(shifterList, currentShifter);
// Add to list of shifted tokens
LinkedList.append(shifterList, _newShifterAddress);
shifterByToken[_tokenAddress] = _newShifterAddress;
emit LogShifterUpdated(_tokenAddress, currentShifter, _newShifterAddress);
}
/// @notice Allows the owner to remove the shifter address for a given
/// ERC20shifter token contract.
///
/// @param _symbol The symbol of the token to deregister.
function removeShifter(string calldata _symbol) external onlyOwner {
// Look up token address
address tokenAddress = tokenBySymbol[_symbol];
require(tokenAddress != address(0x0), "symbol not registered");
// Look up shifter address
address shifterAddress = shifterByToken[tokenAddress];
// Remove token and shifter
shifterByToken[tokenAddress] = address(0x0);
tokenBySymbol[_symbol] = address(0x0);
LinkedList.remove(shifterList, shifterAddress);
LinkedList.remove(shiftedTokenList, tokenAddress);
numShifters -= 1;
emit LogShifterDeregistered(_symbol, _symbol, tokenAddress, shifterAddress);
}
/// @dev To get all the registered shifters use count = 0.
function getShifters(address _start, uint256 _count) external view returns (address[] memory) {
uint256 count;
if (_count == 0) {
count = numShifters;
} else {
count = _count;
}
address[] memory shifters = new address[](count);
// Begin with the first node in the list
uint256 n = 0;
address next = _start;
if (next == address(0)) {
next = LinkedList.begin(shifterList);
}
while (n < count) {
if (next == address(0)) {
break;
}
shifters[n] = next;
next = LinkedList.next(shifterList, next);
n += 1;
}
return shifters;
}
/// @dev To get all the registered shifted tokens use count = 0.
function getShiftedTokens(address _start, uint256 _count) external view returns (address[] memory) {
uint256 count;
if (_count == 0) {
count = numShifters;
} else {
count = _count;
}
address[] memory shiftedTokens = new address[](count);
// Begin with the first node in the list
uint256 n = 0;
address next = _start;
if (next == address(0)) {
next = LinkedList.begin(shiftedTokenList);
}
while (n < count) {
if (next == address(0)) {
break;
}
shiftedTokens[n] = next;
next = LinkedList.next(shiftedTokenList, next);
n += 1;
}
return shiftedTokens;
}
/// @notice Returns the Shifter address for the given ERC20Shifted token
/// contract address.
///
/// @param _tokenAddress The address of the ERC20Shifted token contract.
function getShifterByToken(address _tokenAddress) external view returns (IShifter) {
return IShifter(shifterByToken[_tokenAddress]);
}
/// @notice Returns the Shifter address for the given ERC20Shifted token
/// symbol.
///
/// @param _tokenSymbol The symbol of the ERC20Shifted token contract.
function getShifterBySymbol(string calldata _tokenSymbol) external view returns (IShifter) {
return IShifter(shifterByToken[tokenBySymbol[_tokenSymbol]]);
}
/// @notice Returns the ERC20Shifted address for the given token symbol.
///
/// @param _tokenSymbol The symbol of the ERC20Shifted token contract to
/// lookup.
function getTokenBySymbol(string calldata _tokenSymbol) external view returns (address) {
return tokenBySymbol[_tokenSymbol];
}
}