Line data Source code
1 : // SPDX-License-Identifier: MIT
2 :
3 : pragma solidity ^0.6.12;
4 : pragma experimental ABIEncoderV2;
5 :
6 : // OZ imports
7 :
8 : import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
9 : import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
10 : import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
11 : import { Address } from "@openzeppelin/contracts/utils/Address.sol";
12 : import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
13 :
14 : // Tornado imports
15 :
16 : import { TORN } from "torn-token/contracts/TORN.sol";
17 :
18 : // Local imports
19 :
20 : import { IENS } from "./interfaces/IENS.sol";
21 :
22 : import { ENSNamehash } from "./libraries/ENSNamehash.sol";
23 :
24 : import { ENSResolver } from "./libraries/ENSResolver.sol";
25 :
26 : import { TornadoStakingRewards } from "./TornadoStakingRewards.sol";
27 :
28 : import { FeeOracleManager } from "./FeeOracleManager.sol";
29 :
30 : contract RegistryLegacyStorage {
31 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LEGACY STORAGE, ABANDONED ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
32 :
33 : /**
34 : * @dev From Initializable.sol of first contract
35 : */
36 : bool private _deprecatedInitialized;
37 :
38 : /**
39 : * @dev From Initializable.sol of first contract
40 : */
41 : bool private _deprecatedInitializing;
42 :
43 : /**
44 : * @dev This one will be moved for visibility
45 : */
46 : address private _deprecatedRouterAddress;
47 :
48 : /**
49 : * @dev We are not using this one because we will pull some magic
50 : */
51 : uint256 private _deprecatedMinStakeAmount;
52 :
53 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LEGACY STORAGE, IN USE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
54 :
55 : /**
56 : * @notice Relayer metadata: their (non-refundable) TORN balances and ENS node
57 : */
58 : mapping(address => RelayerMetadata) public metadata;
59 :
60 : /**
61 : * @notice Subaddresses which may work for a given relayer
62 : */
63 : mapping(address => address) public workers;
64 : }
65 :
66 : interface MinimumStakingAmountOracle {
67 : function calculateMinimumStakingAmount() external view returns (uint256);
68 : }
69 :
70 : struct RelayerMetadata {
71 : uint256 balance;
72 : bytes32 node;
73 : }
74 :
75 : contract RelayerRegistry is RegistryLegacyStorage, ENSResolver, Initializable {
76 : using SafeMath for uint256;
77 : using SafeERC20 for IERC20;
78 :
79 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NEW STORAGE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
80 :
81 : /**
82 : * @notice The address of the Governance proxy.
83 : */
84 : address public immutable governanceProxyAddress;
85 :
86 : /**
87 : * @notice The TORN token.
88 : */
89 : TORN public immutable torn;
90 :
91 : /**
92 : * @notice The Staking Rewards proxy which we need to forwards funds
93 : */
94 : address public stakingRewardsProxyAddress;
95 :
96 : /**
97 : * @notice The address from which slashes may come from.
98 : */
99 : address public routerAddress;
100 :
101 : /**
102 : * @notice Since registrations are maybe relatively frequent and this boils down to a view getter, we can
103 : * use a bytes20 to either read out a min stake amount as a number or to fetch it from an address.
104 : */
105 : bytes20 public minStakeAmountOracle;
106 :
107 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EVENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
108 :
109 : // Contract general
110 : event ENSUpdated(address ens);
111 : event RouterAddressUpdated(address routerAddress);
112 : event FeeOracleManagerUpdated(address feeOracleManagerAddress);
113 : event StakingRewardsProxyUpdated(address stakingRewards);
114 : event MinimumStakingAmountOracleUpdated(bytes20 oracle, bool isContract);
115 :
116 : // Relayer metadata
117 : event RelayerRegistered(string ensName, bytes32 relayer, address relayerAddress, uint256 stakedAmount);
118 :
119 : // Relayer Stake
120 : event StakeAddedToRelayer(address relayer, uint256 amountStakeAdded);
121 : event StakeBurned(address relayer, uint256 amountBurned);
122 :
123 : // Relayers workers
124 : event WorkerRegistered(address relayer, address worker);
125 : event WorkerUnregistered(address relayer, address worker);
126 :
127 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
128 :
129 : constructor(address _governanceProxyAddress, address _tornTokenAddress) public {
130 : governanceProxyAddress = _governanceProxyAddress;
131 : torn = TORN(_tornTokenAddress);
132 : }
133 :
134 : modifier onlyGovernance() {
135 : require(msg.sender == governanceProxyAddress, "RelayerRegistry: onlyGovernance");
136 : _;
137 : }
138 :
139 : modifier onlyRouter() {
140 : require(msg.sender == routerAddress, "RelayerRegistry: onlyRouter");
141 : _;
142 : }
143 :
144 : modifier onlyRelayer(address _possibleRelayer, address _possibleWorker) {
145 : require(isWorkerOfRelayer(_possibleRelayer, _possibleWorker), "RelayerRegistry: onlyRelayer");
146 : _;
147 : }
148 :
149 : modifier onlyENSOwner(address _relayer, bytes32 _node) {
150 : require(_relayer == ownerByNode(_node), "RelayerRegistry: onlyENSOwner");
151 : _;
152 : }
153 :
154 : function version() public pure virtual returns (string memory) {
155 0 : return "v2-oracle-manager";
156 : }
157 :
158 : function initialize(
159 : address _routerAddress,
160 : address _stakingRewardsProxyAddress,
161 : bytes20 _minStakeAmountOracle
162 : ) public virtual initializer {
163 4 : routerAddress = _routerAddress;
164 4 : minStakeAmountOracle = _minStakeAmountOracle;
165 4 : stakingRewardsProxyAddress = _stakingRewardsProxyAddress;
166 : }
167 :
168 : function register(string calldata _name, uint256 _staked, address[] calldata _workers) public virtual {
169 1 : _register(_name, ENSNamehash.namehash(bytes(_name)), msg.sender, _staked, _workers);
170 : }
171 :
172 : function registerPermit(
173 : string calldata _name,
174 : uint256 _staked,
175 : address[] calldata _workers,
176 : address _relayer,
177 : uint256 _deadline,
178 : uint8 v,
179 : bytes32 r,
180 : bytes32 s
181 : ) public virtual {
182 0 : torn.permit(_relayer, address(this), _staked, _deadline, v, r, s);
183 0 : _register(_name, ENSNamehash.namehash(bytes(_name)), _relayer, _staked, _workers);
184 : }
185 :
186 : function _register(
187 : string memory _name,
188 : bytes32 _node,
189 : address _relayer,
190 : uint256 _staked,
191 : address[] calldata _workers
192 : ) internal onlyENSOwner(_relayer, _node) {
193 1 : bytes32 currentNodeValue = metadata[_relayer].node;
194 :
195 1 : require(
196 : workers[_relayer] == address(0) && currentNodeValue == bytes32(0),
197 : "RelayerRegistry: already registered"
198 : );
199 :
200 : // Check if a sufficient amount of TORN is to be staked
201 1 : require(getMinimumStakingAmount() <= _staked, "RelayerRegistry: stake too low");
202 :
203 : // Then transfer it here
204 1 : IERC20(torn).safeTransferFrom(_relayer, address(stakingRewardsProxyAddress), _staked);
205 :
206 : // Then store metadata ("register")
207 1 : metadata[_relayer] = RelayerMetadata({ balance: _staked, node: _node });
208 :
209 1 : workers[_relayer] = _relayer;
210 :
211 1 : for (uint256 i = 0; i < _workers.length; i++) {
212 3 : _registerWorker(_relayer, _workers[i]);
213 : }
214 :
215 1 : emit RelayerRegistered(_name, _node, _relayer, _staked);
216 : }
217 :
218 : function registerWorker(address _relayer, address _worker)
219 : public
220 : virtual
221 : onlyRelayer(_relayer, msg.sender)
222 : {
223 0 : _registerWorker(_relayer, _worker);
224 : }
225 :
226 : function _registerWorker(address _relayer, address _worker) internal {
227 3 : require(workers[_worker] == address(0), "RelayerRegistry: already registered");
228 3 : workers[_worker] = _relayer;
229 3 : emit WorkerRegistered(_relayer, _worker);
230 : }
231 :
232 : function unregisterWorker(address _worker) public virtual {
233 4 : require(
234 : msg.sender == _worker || isWorkerOfRelayer(msg.sender, _worker),
235 : "RelayerRegistry: sender must own worker"
236 : );
237 :
238 3 : require(workers[_worker] != _worker, "RelayerRegistry: cant remove owner");
239 :
240 3 : workers[_worker] = address(0);
241 :
242 3 : emit WorkerUnregistered(workers[_worker], _worker);
243 : }
244 :
245 : function stakeToRelayer(address _relayer, uint256 _staked) public virtual {
246 1 : _addStake(msg.sender, _relayer, _staked);
247 : }
248 :
249 : function stakeToRelayerPermit(
250 : address _relayer,
251 : uint256 _staked,
252 : address _staker,
253 : uint256 _deadline,
254 : uint8 v,
255 : bytes32 r,
256 : bytes32 s
257 : ) public virtual {
258 0 : torn.permit(_staker, address(this), _staked, _deadline, v, r, s);
259 0 : _addStake(_staker, _relayer, _staked);
260 : }
261 :
262 : function _addStake(address _staker, address _relayer, uint256 _staked)
263 : internal
264 : onlyRelayer(_relayer, _relayer)
265 : {
266 1 : IERC20(torn).safeTransferFrom(_staker, address(stakingRewardsProxyAddress), _staked);
267 1 : metadata[_relayer].balance = _staked.add(metadata[_relayer].balance);
268 1 : emit StakeAddedToRelayer(_relayer, _staked);
269 : }
270 :
271 : function deductBalance(address _sender, address _relayer, uint256 _burned)
272 : public
273 : virtual
274 : onlyRouter
275 : onlyRelayer(_relayer, _sender)
276 : {
277 1 : metadata[_relayer].balance = metadata[_relayer].balance.sub(_burned);
278 1 : emit StakeBurned(_relayer, _burned);
279 : }
280 :
281 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SETTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
282 :
283 : function setRouterAddress(address _newRouterAddress) public virtual onlyGovernance {
284 0 : routerAddress = _newRouterAddress;
285 0 : emit RouterAddressUpdated(_newRouterAddress);
286 : }
287 :
288 : function setStakingRewardsProxyAddress(address _newStakingRewardsProxyAddress)
289 : public
290 : virtual
291 : onlyGovernance
292 : {
293 0 : stakingRewardsProxyAddress = _newStakingRewardsProxyAddress;
294 0 : emit StakingRewardsProxyUpdated(_newStakingRewardsProxyAddress);
295 : }
296 :
297 : function setMinimumStakingAmountOracle(bytes20 _newOracle, bool _isContractOracle)
298 : public
299 : virtual
300 : onlyGovernance
301 : {
302 0 : bool oracleIsContract = Address.isContract(address(_newOracle));
303 0 : require(_isContractOracle == oracleIsContract, "RelayerRegistry: oracle not expected type");
304 0 : minStakeAmountOracle = _newOracle;
305 0 : emit MinimumStakingAmountOracleUpdated(_newOracle, oracleIsContract);
306 : }
307 :
308 : /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GETTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
309 :
310 : function isWorker(address _possibleWorker) public view virtual returns (bool) {
311 1 : return workers[_possibleWorker] != address(0);
312 : }
313 :
314 : function isWorkerOfRelayer(address _possibleRelayer, address _possibleWorker)
315 : public
316 : view
317 : virtual
318 : returns (bool)
319 : {
320 5 : return _possibleRelayer == workers[_possibleWorker];
321 : }
322 :
323 : function getOwningRelayerOfWorker(address _worker) public view virtual returns (address) {
324 0 : return workers[_worker];
325 : }
326 :
327 : function getMinimumStakingAmount() public view virtual returns (uint256) {
328 1 : bytes20 _minStakeAmountOracle = minStakeAmountOracle;
329 1 : if (Address.isContract(address(_minStakeAmountOracle))) {
330 0 : return MinimumStakingAmountOracle(address(_minStakeAmountOracle)).calculateMinimumStakingAmount();
331 : }
332 1 : return uint160(_minStakeAmountOracle);
333 : }
334 :
335 : function getRelayerBalanceByName(string memory _name) public view virtual returns (uint256) {
336 2 : return metadata[ownerByName(_name)].balance;
337 : }
338 :
339 : function getRelayerENSNodeByName(string memory _name) public view virtual returns (bytes32) {
340 0 : return metadata[ownerByName(_name)].node;
341 : }
342 :
343 : function getRelayerBalance(address _relayer) public view virtual returns (uint256) {
344 0 : return metadata[workers[_relayer]].balance;
345 : }
346 :
347 : function getRelayerENSNode(address _relayer) public view virtual returns (bytes32) {
348 0 : return metadata[workers[_relayer]].node;
349 : }
350 : }
|