Line data Source code
1 : // SPDX-License-Identifier: MIT
2 :
3 : pragma solidity >=0.6.0 <0.8.0;
4 : pragma experimental ABIEncoderV2;
5 :
6 : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7 : import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
8 : import "@openzeppelin/contracts/math/Math.sol";
9 : import "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol";
10 : import "torn-token/contracts/ENS.sol";
11 : import "./InstanceRegistry.sol";
12 : import "../RelayerRegistry.sol";
13 :
14 : contract TornadoRouter is EnsResolve {
15 : using SafeERC20 for IERC20;
16 :
17 : event EncryptedNote(address indexed sender, bytes encryptedNote);
18 :
19 : address public immutable governance;
20 : InstanceRegistry public immutable instanceRegistry;
21 : RelayerRegistry public immutable relayerRegistry;
22 :
23 : modifier onlyGovernance() {
24 : require(msg.sender == governance, "Not authorized");
25 : _;
26 : }
27 :
28 : modifier onlyInstanceRegistry() {
29 : require(msg.sender == address(instanceRegistry), "Not authorized");
30 : _;
31 : }
32 :
33 : constructor(
34 : address _governance,
35 : bytes32 _instanceRegistry,
36 : bytes32 _relayerRegistry
37 : ) public {
38 : governance = _governance;
39 : instanceRegistry = InstanceRegistry(resolve(_instanceRegistry));
40 : relayerRegistry = RelayerRegistry(resolve(_relayerRegistry));
41 : }
42 :
43 : function deposit(
44 : ITornadoInstance _tornado,
45 : bytes32 _commitment,
46 : bytes calldata _encryptedNote
47 : ) public payable virtual {
48 0 : (bool isERC20, IERC20 token, InstanceRegistry.InstanceState state, , ) = instanceRegistry.instances(_tornado);
49 0 : require(state != InstanceRegistry.InstanceState.DISABLED, "The instance is not supported");
50 :
51 0 : if (isERC20) {
52 0 : token.safeTransferFrom(msg.sender, address(this), _tornado.denomination());
53 : }
54 0 : _tornado.deposit{ value: msg.value }(_commitment);
55 0 : emit EncryptedNote(msg.sender, _encryptedNote);
56 : }
57 :
58 : function withdraw(
59 : ITornadoInstance _tornado,
60 : bytes calldata _proof,
61 : bytes32 _root,
62 : bytes32 _nullifierHash,
63 : address payable _recipient,
64 : address payable _relayer,
65 : uint256 _fee,
66 : uint256 _refund
67 : ) public payable virtual {
68 0 : (, , InstanceRegistry.InstanceState state, , ) = instanceRegistry.instances(_tornado);
69 0 : require(state != InstanceRegistry.InstanceState.DISABLED, "The instance is not supported");
70 0 : relayerRegistry.burn(msg.sender, _relayer, _tornado);
71 :
72 0 : _tornado.withdraw{ value: msg.value }(_proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund);
73 : }
74 :
75 : /**
76 : * @dev Sets `amount` allowance of `_spender` over the router's (this contract) tokens.
77 : */
78 : function approveExactToken(
79 : IERC20 _token,
80 : address _spender,
81 : uint256 _amount
82 : ) external onlyInstanceRegistry {
83 0 : _token.safeApprove(_spender, _amount);
84 : }
85 :
86 : /**
87 : * @notice Manually backup encrypted notes
88 : */
89 : function backupNotes(bytes[] calldata _encryptedNotes) external virtual {
90 0 : for (uint256 i = 0; i < _encryptedNotes.length; i++) {
91 0 : emit EncryptedNote(msg.sender, _encryptedNotes[i]);
92 : }
93 : }
94 :
95 : /// @dev Method to claim junk and accidentally sent tokens
96 : function rescueTokens(
97 : IERC20 _token,
98 : address payable _to,
99 : uint256 _amount
100 : ) external virtual onlyGovernance {
101 0 : require(_to != address(0), "TORN: can not send to zero address");
102 :
103 0 : if (_token == IERC20(0)) {
104 : // for Ether
105 0 : uint256 totalBalance = address(this).balance;
106 0 : uint256 balance = Math.min(totalBalance, _amount);
107 0 : _to.transfer(balance);
108 : } else {
109 : // any other erc20
110 0 : uint256 totalBalance = _token.balanceOf(address(this));
111 0 : uint256 balance = Math.min(totalBalance, _amount);
112 0 : require(balance > 0, "TORN: trying to send 0 balance");
113 0 : _token.safeTransfer(_to, balance);
114 : }
115 : }
116 : }
|