More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 143,954 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Deposit | 15362174 | 948 days ago | IN | 0.1 ETH | 0.00016365 | ||||
Deposit | 15362148 | 948 days ago | IN | 0.1 ETH | 0.00017669 | ||||
Deposit | 15242019 | 966 days ago | IN | 0.1 ETH | 0.00007637 | ||||
Deposit | 15199055 | 973 days ago | IN | 0.1 ETH | 0.00010183 | ||||
Deposit | 15197955 | 973 days ago | IN | 0 ETH | 0.00010438 | ||||
Deposit | 15190538 | 974 days ago | IN | 0.1 ETH | 0.00012729 | ||||
Deposit | 15061564 | 994 days ago | IN | 0.1 ETH | 0.00017821 | ||||
Deposit | 14990948 | 1007 days ago | IN | 10 ETH | 0.00063647 | ||||
Deposit | 14990945 | 1007 days ago | IN | 10 ETH | 0.00063647 | ||||
Deposit | 14990940 | 1007 days ago | IN | 10 ETH | 0.00063647 | ||||
Deposit | 14990934 | 1007 days ago | IN | 10 ETH | 0.00063647 | ||||
Deposit | 14716290 | 1052 days ago | IN | 100 ETH | 0.00085434 | ||||
Withdraw | 14384356 | 1104 days ago | IN | 0 ETH | 0.00055897 | ||||
Deposit | 14370560 | 1106 days ago | IN | 0.1 ETH | 0.00028004 | ||||
Deposit | 14355369 | 1109 days ago | IN | 1 ETH | 0.00057933 | ||||
Deposit | 14353966 | 1109 days ago | IN | 1 ETH | 0.00138443 | ||||
Deposit | 14351925 | 1109 days ago | IN | 1 ETH | 0.00051781 | ||||
Deposit | 14351906 | 1109 days ago | IN | 1 ETH | 0.0006125 | ||||
Deposit | 14351002 | 1109 days ago | IN | 0.1 ETH | 0.00083961 | ||||
Deposit | 14342159 | 1111 days ago | IN | 1 ETH | 0.00164588 | ||||
Deposit | 14342119 | 1111 days ago | IN | 1 ETH | 0.00191451 | ||||
Deposit | 14341180 | 1111 days ago | IN | 0.1 ETH | 0.00080413 | ||||
Deposit | 14339180 | 1111 days ago | IN | 10 ETH | 0.00059511 | ||||
Deposit | 14339156 | 1111 days ago | IN | 10 ETH | 0.00053997 | ||||
Deposit | 14333895 | 1112 days ago | IN | 1 ETH | 0.00076676 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
- | 14248698 | 1125 days ago | 10 ETH | ||||
- | 14248657 | 1125 days ago | 0.1 ETH | ||||
- | 14248545 | 1125 days ago | 0.1 ETH | ||||
- | 14248545 | 1125 days ago | 0.1 ETH | ||||
- | 14248545 | 1125 days ago | 0.1 ETH | ||||
- | 14248545 | 1125 days ago | 0.1 ETH | ||||
- | 14248529 | 1125 days ago | 1 ETH | ||||
- | 14248484 | 1125 days ago | 1 ETH | ||||
- | 14248447 | 1125 days ago | 10 ETH | ||||
- | 14248319 | 1125 days ago | 10 ETH | ||||
- | 14248281 | 1125 days ago | 10 ETH | ||||
- | 14248281 | 1125 days ago | 10 ETH | ||||
- | 14248281 | 1125 days ago | 10 ETH | ||||
- | 14248201 | 1125 days ago | 10 ETH | ||||
- | 14248170 | 1125 days ago | 0.1 ETH | ||||
- | 14248104 | 1125 days ago | 100 ETH | ||||
- | 14248091 | 1125 days ago | 100 ETH | ||||
- | 14248062 | 1125 days ago | 1 ETH | ||||
- | 14248010 | 1125 days ago | 100 ETH | ||||
- | 14247980 | 1125 days ago | 0.1 ETH | ||||
- | 14247968 | 1125 days ago | 100 ETH | ||||
- | 14247852 | 1125 days ago | 1 ETH | ||||
- | 14247838 | 1125 days ago | 10 ETH | ||||
- | 14247816 | 1125 days ago | 10 ETH | ||||
- | 14247816 | 1125 days ago | 1 ETH |
Loading...
Loading
Contract Name:
TornadoProxy
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/math/Math.sol"; import "./interfaces/ITornadoInstance.sol"; import "./interfaces/ITornadoTrees.sol"; contract TornadoProxy { using SafeERC20 for IERC20; event EncryptedNote(address indexed sender, bytes encryptedNote); event InstanceStateUpdated(ITornadoInstance indexed instance, InstanceState state); event TornadoTreesUpdated(ITornadoTrees addr); enum InstanceState { DISABLED, ENABLED, MINEABLE } struct Instance { bool isERC20; IERC20 token; InstanceState state; } struct Tornado { ITornadoInstance addr; Instance instance; } ITornadoTrees public tornadoTrees; address public immutable governance; mapping(ITornadoInstance => Instance) public instances; modifier onlyGovernance() { require(msg.sender == governance, "Not authorized"); _; } constructor( address _tornadoTrees, address _governance, Tornado[] memory _instances ) public { tornadoTrees = ITornadoTrees(_tornadoTrees); governance = _governance; for (uint256 i = 0; i < _instances.length; i++) { _updateInstance(_instances[i]); } } function deposit( ITornadoInstance _tornado, bytes32 _commitment, bytes calldata _encryptedNote ) external payable { Instance memory instance = instances[_tornado]; require(instance.state != InstanceState.DISABLED, "The instance is not supported"); if (instance.isERC20) { instance.token.safeTransferFrom(msg.sender, address(this), _tornado.denomination()); } _tornado.deposit{ value: msg.value }(_commitment); if (instance.state == InstanceState.MINEABLE) { tornadoTrees.registerDeposit(address(_tornado), _commitment); } emit EncryptedNote(msg.sender, _encryptedNote); } function withdraw( ITornadoInstance _tornado, bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund ) external payable { Instance memory instance = instances[_tornado]; require(instance.state != InstanceState.DISABLED, "The instance is not supported"); _tornado.withdraw{ value: msg.value }(_proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund); if (instance.state == InstanceState.MINEABLE) { tornadoTrees.registerWithdrawal(address(_tornado), _nullifierHash); } } function backupNotes(bytes[] calldata _encryptedNotes) external { for (uint256 i = 0; i < _encryptedNotes.length; i++) { emit EncryptedNote(msg.sender, _encryptedNotes[i]); } } function updateInstance(Tornado calldata _tornado) external onlyGovernance { _updateInstance(_tornado); } function setTornadoTreesContract(ITornadoTrees _tornadoTrees) external onlyGovernance { tornadoTrees = _tornadoTrees; emit TornadoTreesUpdated(_tornadoTrees); } /// @dev Method to claim junk and accidentally sent tokens function rescueTokens( IERC20 _token, address payable _to, uint256 _amount ) external onlyGovernance { require(_to != address(0), "TORN: can not send to zero address"); if (_token == IERC20(0)) { // for Ether uint256 totalBalance = address(this).balance; uint256 balance = Math.min(totalBalance, _amount); _to.transfer(balance); } else { // any other erc20 uint256 totalBalance = _token.balanceOf(address(this)); uint256 balance = Math.min(totalBalance, _amount); require(balance > 0, "TORN: trying to send 0 balance"); _token.safeTransfer(_to, balance); } } function _updateInstance(Tornado memory _tornado) internal { instances[_tornado.addr] = _tornado.instance; if (_tornado.instance.isERC20) { IERC20 token = IERC20(_tornado.addr.token()); require(token == _tornado.instance.token, "Incorrect token"); uint256 allowance = token.allowance(address(this), address(_tornado.addr)); if (_tornado.instance.state != InstanceState.DISABLED && allowance == 0) { token.safeApprove(address(_tornado.addr), uint256(-1)); } else if (_tornado.instance.state == InstanceState.DISABLED && allowance != 0) { token.safeApprove(address(_tornado.addr), 0); } } emit InstanceStateUpdated(_tornado.addr, _tornado.instance.state); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface IMiner { function setTornadoTreesContract(address _tornadoTrees) external; }
/* This is a proposal to update the TornadoTrees smart contract. It significantly reduces the cost of updating tornado merkle trees by offloading onchain updates to zkSNARKs. The proposal will: - disable old tornado proxy - deploy new contracts: - TornadoTrees - new contract for tree updates - AdminUpgradeableProxy - upgradeability proxy for TornadoTrees - TornadoProxy - new tornado proxy with ERC20 support - migrate state from old TornadoTrees contract to the new one - set deployed AdminUpgradeableProxy as new a tree contract in Miner More info: https://torn.community/t/anonymity-mining-technical-overview/15 */ //SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "tornado-trees/contracts/interfaces/ITornadoTreesV1.sol"; import "tornado-trees/contracts/interfaces/IBatchTreeUpdateVerifier.sol"; import "tornado-trees/contracts/TornadoTrees.sol"; import "tornado-trees/contracts/AdminUpgradeableProxy.sol"; import "tornado-anonymity-mining/contracts/TornadoProxy.sol"; import "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol"; import "torn-token/contracts/ENS.sol"; import "./interfaces/ITornadoProxyV1.sol"; import "./interfaces/IMiner.sol"; contract Proposal is EnsResolve { ITornadoTreesV1 public constant tornadoTreesV1 = ITornadoTreesV1(0x43a3bE4Ae954d9869836702AFd10393D3a7Ea417); ITornadoProxyV1 public constant tornadoProxyV1 = ITornadoProxyV1(0x905b63Fff465B9fFBF41DeA908CEb12478ec7601); IMiner public constant miner = IMiner(0x746Aebc06D2aE31B71ac51429A19D54E797878E9); event DeploymentOf(string name, address addr); address public immutable verifier; // params used to search for array lengths on V1 contracts uint256 private immutable depositsFrom; uint256 private immutable depositsStep; uint256 private immutable withdrawalsFrom; uint256 private immutable withdrawalsStep; constructor( address _verifier, uint256 _depositsFrom, uint256 _depositsStep, uint256 _withdrawalsFrom, uint256 _withdrawalsStep ) public { verifier = _verifier; depositsFrom = _depositsFrom; depositsStep = _depositsStep; withdrawalsFrom = _withdrawalsFrom; withdrawalsStep = _withdrawalsStep; } function executeProposal() public { // Disable all instances on old tornado proxy bytes32[4] memory miningInstances = getEthInstances(); for (uint256 i = 0; i < miningInstances.length; i++) { tornadoProxyV1.updateInstance(resolve(miningInstances[i]), false); } // Deploy new TornadoTrees implementation TornadoTrees tornadoTreesImpl = new TornadoTrees(address(this), tornadoTreesV1, getSearchParams()); emit DeploymentOf("TornadoTrees implementation", address(tornadoTreesImpl)); // Deploy TornadoTrees upgradeable proxy AdminUpgradeableProxy upgradeableProxy = new AdminUpgradeableProxy(address(tornadoTreesImpl), address(this), ""); TornadoTrees tornadoTrees = TornadoTrees(address(upgradeableProxy)); emit DeploymentOf("TornadoTrees upgradeable proxy", address(upgradeableProxy)); // Deploy new TornadoProxy TornadoProxy tornadoProxy = new TornadoProxy(address(tornadoTrees), address(this), getInstances()); emit DeploymentOf("TornadoProxy", address(tornadoProxy)); // Init tornado trees tornadoTrees.initialize(address(tornadoProxy), IBatchTreeUpdateVerifier(verifier)); // Update TornadoTrees address on the mining contract miner.setTornadoTreesContract(address(tornadoTrees)); } function getSearchParams() public view returns (TornadoTrees.SearchParams memory) { return TornadoTrees.SearchParams({ depositsFrom: depositsFrom, depositsStep: depositsStep, withdrawalsFrom: withdrawalsFrom, withdrawalsStep: withdrawalsStep }); } function getEthInstances() internal pure returns (bytes32[4] memory) { return [ bytes32(0xc041982b4f77cbbd82ef3b9ea748738ac6c281d3f1af198770d29f75ac32d80a), // eth-01.tornadocash.eth bytes32(0x9e5bc9215eecd103644145a5db4f69d5efaf4885bb5bf968f8db271ec5cd539b), // eth-1.tornadocash.eth bytes32(0x917e42347647689051abc744f502bff342c76ad30c0670b46b305b2f7e1f893d), // eth-10.tornadocash.eth bytes32(0xddfc726d74f912f49389ef7471e75291969852ce7e5df0509a17bc1e46646985) // eth-100.tornadocash.eth ]; } function getErc20Instances() internal pure returns (bytes32[15] memory) { return [ bytes32(0x95ad5771ba164db3fc73cc74d4436cb6a6babd7a2774911c69d8caae30410982), // dai-100.tornadocash.eth bytes32(0x109d0334da83a2c3a687972cc806b0eda52ee7a30f3e44e77b39ae2a20248321), // dai-1000.tornadocash.eth bytes32(0x3de4b55be5058f538617d5a6a72bff5b5850a239424b34cc5271021cfcc4ccc8), // dai-10000.tornadocash.eth bytes32(0xf50559e0d2f0213bcb8c67ad45b93308b46b9abdd5ca9c7044efc025fc557f59), // dai-100000.tornadocash.eth bytes32(0xc9395879ffcee571b0dfd062153b27d62a6617e0f272515f2eb6259fe829c3df), // cdai-5000.tornadocash.eth bytes32(0xf840ad6cba4dbbab0fa58a13b092556cd53a6eeff716a3c4a41d860a888b6155), // cdai-50000.tornadocash.eth bytes32(0x8e52ade66daf81cf3f50053e9bfca86a57d685eca96bf6c0b45da481806952b1), // cdai-500000.tornadocash.eth bytes32(0x0b86f5b8c2f9dcd95382a469480b35302eead707f3fd36359e346b59f3591de2), // cdai-5000000.tornadocash.eth bytes32(0xd49809328056ea7b7be70076070bf741ec1a27b86bebafdc484eee88c1834191), // usdc-100.tornadocash.eth bytes32(0x77e2b15eddc494b6da6cee0d797ed30ed3945f2c7de0150f16f0405a12e5665f), // usdc-1000.tornadocash.eth bytes32(0x36bab2c045f88613be6004ec1dc0c3937941fcf4d4cb78d814c933bf1cf25baf), // usdt-100.tornadocash.eth bytes32(0x7a3b0883165756c26821d9b8c9737166a156a78b478b17e42da72fba7a373356), // usdt-1000.tornadocash.eth bytes32(0x10ca74c40211fa1598f0531f35c7d54c19c808082aad53c72ad1fb22ea94ab83), // wbtc-01.tornadocash.eth bytes32(0x6cea0cba8e46fc4ffaf837edf544ba36e5a35503636c6bca4578e965ab640e2c), // wbtc-1.tornadocash.eth bytes32(0x82c57bf2f80547b5e31b92c1f92c4f8bc02ad0df3d27326373e9f55adda5bd15) // wbtc-10.tornadocash.eth ]; } function getInstances() public view returns (TornadoProxy.Tornado[] memory instances) { bytes32[4] memory miningInstances = getEthInstances(); bytes32[15] memory allowedInstances = getErc20Instances(); instances = new TornadoProxy.Tornado[](allowedInstances.length + miningInstances.length); for (uint256 i = 0; i < miningInstances.length; i++) { // Enable mining for ETH instances instances[i] = TornadoProxy.Tornado( ITornadoInstance(resolve(miningInstances[i])), TornadoProxy.Instance({ isERC20: false, token: IERC20(address(0)), state: TornadoProxy.InstanceState.MINEABLE }) ); } for (uint256 i = 0; i < allowedInstances.length; i++) { // ERC20 are only allowed on proxy without enabling mining for them ITornadoInstance instance = ITornadoInstance(resolve(allowedInstances[i])); instances[miningInstances.length + i] = TornadoProxy.Tornado({ addr: instance, instance: TornadoProxy.Instance({ isERC20: true, token: IERC20(instance.token()), state: TornadoProxy.InstanceState.ENABLED }) }); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ITornadoTreesV1 { function lastProcessedDepositLeaf() external view returns (uint256); function lastProcessedWithdrawalLeaf() external view returns (uint256); function depositRoot() external view returns (bytes32); function withdrawalRoot() external view returns (bytes32); function deposits(uint256 i) external view returns (bytes32); function withdrawals(uint256 i) external view returns (bytes32); function registerDeposit(address instance, bytes32 commitment) external; function registerWithdrawal(address instance, bytes32 nullifier) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface IBatchTreeUpdateVerifier { function verifyProof(bytes calldata proof, uint256[1] calldata input) external view returns (bool); }
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "./interfaces/ITornadoTreesV1.sol"; import "./interfaces/IBatchTreeUpdateVerifier.sol"; import "@openzeppelin/upgrades-core/contracts/Initializable.sol"; /// @dev This contract holds a merkle tree of all tornado cash deposit and withdrawal events contract TornadoTrees is Initializable { address public immutable governance; bytes32 public depositRoot; bytes32 public previousDepositRoot; bytes32 public withdrawalRoot; bytes32 public previousWithdrawalRoot; address public tornadoProxy; IBatchTreeUpdateVerifier public treeUpdateVerifier; ITornadoTreesV1 public immutable tornadoTreesV1; uint256 public constant CHUNK_TREE_HEIGHT = 8; uint256 public constant CHUNK_SIZE = 2**CHUNK_TREE_HEIGHT; uint256 public constant ITEM_SIZE = 32 + 20 + 4; uint256 public constant BYTES_SIZE = 32 + 32 + 4 + CHUNK_SIZE * ITEM_SIZE; uint256 public constant SNARK_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; mapping(uint256 => bytes32) public deposits; uint256 public depositsLength; uint256 public lastProcessedDepositLeaf; uint256 public immutable depositsV1Length; mapping(uint256 => bytes32) public withdrawals; uint256 public withdrawalsLength; uint256 public lastProcessedWithdrawalLeaf; uint256 public immutable withdrawalsV1Length; event DepositData(address instance, bytes32 indexed hash, uint256 block, uint256 index); event WithdrawalData(address instance, bytes32 indexed hash, uint256 block, uint256 index); event VerifierUpdated(address newVerifier); event ProxyUpdated(address newProxy); struct TreeLeaf { bytes32 hash; address instance; uint32 block; } modifier onlyTornadoProxy { require(msg.sender == tornadoProxy, "Not authorized"); _; } modifier onlyGovernance() { require(msg.sender == governance, "Only governance can perform this action"); _; } struct SearchParams { uint256 depositsFrom; uint256 depositsStep; uint256 withdrawalsFrom; uint256 withdrawalsStep; } constructor( address _governance, ITornadoTreesV1 _tornadoTreesV1, SearchParams memory _searchParams ) public { governance = _governance; tornadoTreesV1 = _tornadoTreesV1; depositsV1Length = findArrayLength( _tornadoTreesV1, "deposits(uint256)", _searchParams.depositsFrom, _searchParams.depositsStep ); withdrawalsV1Length = findArrayLength( _tornadoTreesV1, "withdrawals(uint256)", _searchParams.withdrawalsFrom, _searchParams.withdrawalsStep ); } function initialize(address _tornadoProxy, IBatchTreeUpdateVerifier _treeUpdateVerifier) public initializer onlyGovernance { tornadoProxy = _tornadoProxy; treeUpdateVerifier = _treeUpdateVerifier; depositRoot = tornadoTreesV1.depositRoot(); uint256 lastDepositLeaf = tornadoTreesV1.lastProcessedDepositLeaf(); require(lastDepositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); lastProcessedDepositLeaf = lastDepositLeaf; depositsLength = depositsV1Length; withdrawalRoot = tornadoTreesV1.withdrawalRoot(); uint256 lastWithdrawalLeaf = tornadoTreesV1.lastProcessedWithdrawalLeaf(); require(lastWithdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); lastProcessedWithdrawalLeaf = lastWithdrawalLeaf; withdrawalsLength = withdrawalsV1Length; } /// @dev Queue a new deposit data to be inserted into a merkle tree function registerDeposit(address _instance, bytes32 _commitment) public onlyTornadoProxy { uint256 _depositsLength = depositsLength; deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber())); emit DepositData(_instance, _commitment, blockNumber(), _depositsLength); depositsLength = _depositsLength + 1; } /// @dev Queue a new withdrawal data to be inserted into a merkle tree function registerWithdrawal(address _instance, bytes32 _nullifierHash) public onlyTornadoProxy { uint256 _withdrawalsLength = withdrawalsLength; withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber())); emit WithdrawalData(_instance, _nullifierHash, blockNumber(), _withdrawalsLength); withdrawalsLength = _withdrawalsLength + 1; } /// @dev Insert a full batch of queued deposits into a merkle tree /// @param _proof A snark proof that elements were inserted correctly /// @param _argsHash A hash of snark inputs /// @param _argsHash Current merkle tree root /// @param _newRoot Updated merkle tree root /// @param _pathIndices Merkle path to inserted batch /// @param _events A batch of inserted events (leaves) function updateDepositTree( bytes calldata _proof, bytes32 _argsHash, bytes32 _currentRoot, bytes32 _newRoot, uint32 _pathIndices, TreeLeaf[CHUNK_SIZE] calldata _events ) public { uint256 offset = lastProcessedDepositLeaf; require(_currentRoot == depositRoot, "Proposed deposit root is invalid"); require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect deposit insert index"); bytes memory data = new bytes(BYTES_SIZE); assembly { mstore(add(data, 0x44), _pathIndices) mstore(add(data, 0x40), _newRoot) mstore(add(data, 0x20), _currentRoot) } for (uint256 i = 0; i < CHUNK_SIZE; i++) { (bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block); bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber)); bytes32 deposit = offset + i >= depositsV1Length ? deposits[offset + i] : tornadoTreesV1.deposits(offset + i); require(leafHash == deposit, "Incorrect deposit"); assembly { let itemOffset := add(data, mul(ITEM_SIZE, i)) mstore(add(itemOffset, 0x7c), blockNumber) mstore(add(itemOffset, 0x78), instance) mstore(add(itemOffset, 0x64), hash) } if (offset + i >= depositsV1Length) { delete deposits[offset + i]; } else { emit DepositData(instance, hash, blockNumber, offset + i); } } uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD; require(argsHash == uint256(_argsHash), "Invalid args hash"); require(treeUpdateVerifier.verifyProof(_proof, [argsHash]), "Invalid deposit tree update proof"); previousDepositRoot = _currentRoot; depositRoot = _newRoot; lastProcessedDepositLeaf = offset + CHUNK_SIZE; } /// @dev Insert a full batch of queued withdrawals into a merkle tree /// @param _proof A snark proof that elements were inserted correctly /// @param _argsHash A hash of snark inputs /// @param _argsHash Current merkle tree root /// @param _newRoot Updated merkle tree root /// @param _pathIndices Merkle path to inserted batch /// @param _events A batch of inserted events (leaves) function updateWithdrawalTree( bytes calldata _proof, bytes32 _argsHash, bytes32 _currentRoot, bytes32 _newRoot, uint32 _pathIndices, TreeLeaf[CHUNK_SIZE] calldata _events ) public { uint256 offset = lastProcessedWithdrawalLeaf; require(_currentRoot == withdrawalRoot, "Proposed withdrawal root is invalid"); require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect withdrawal insert index"); bytes memory data = new bytes(BYTES_SIZE); assembly { mstore(add(data, 0x44), _pathIndices) mstore(add(data, 0x40), _newRoot) mstore(add(data, 0x20), _currentRoot) } for (uint256 i = 0; i < CHUNK_SIZE; i++) { (bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block); bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber)); bytes32 withdrawal = offset + i >= withdrawalsV1Length ? withdrawals[offset + i] : tornadoTreesV1.withdrawals(offset + i); require(leafHash == withdrawal, "Incorrect withdrawal"); assembly { let itemOffset := add(data, mul(ITEM_SIZE, i)) mstore(add(itemOffset, 0x7c), blockNumber) mstore(add(itemOffset, 0x78), instance) mstore(add(itemOffset, 0x64), hash) } if (offset + i >= withdrawalsV1Length) { delete withdrawals[offset + i]; } else { emit WithdrawalData(instance, hash, blockNumber, offset + i); } } uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD; require(argsHash == uint256(_argsHash), "Invalid args hash"); require(treeUpdateVerifier.verifyProof(_proof, [argsHash]), "Invalid withdrawal tree update proof"); previousWithdrawalRoot = _currentRoot; withdrawalRoot = _newRoot; lastProcessedWithdrawalLeaf = offset + CHUNK_SIZE; } function validateRoots(bytes32 _depositRoot, bytes32 _withdrawalRoot) public view { require(_depositRoot == depositRoot || _depositRoot == previousDepositRoot, "Incorrect deposit tree root"); require(_withdrawalRoot == withdrawalRoot || _withdrawalRoot == previousWithdrawalRoot, "Incorrect withdrawal tree root"); } /// @dev There is no array length getter for deposit and withdrawal arrays /// in the previous contract, so we have to find them length manually. /// Used only during deployment function findArrayLength( ITornadoTreesV1 _tornadoTreesV1, string memory _type, uint256 _from, // most likely array length after the proposal has passed uint256 _step // optimal step size to find first match, approximately equals dispersion ) internal view virtual returns (uint256) { // Find the segment with correct array length bool direction = elementExists(_tornadoTreesV1, _type, _from); do { _from = direction ? _from + _step : _from - _step; } while (direction == elementExists(_tornadoTreesV1, _type, _from)); uint256 high = direction ? _from : _from + _step; uint256 low = direction ? _from - _step : _from; uint256 mid = (high + low) / 2; // Perform a binary search in this segment while (low < mid) { if (elementExists(_tornadoTreesV1, _type, mid)) { low = mid; } else { high = mid; } mid = (low + high) / 2; } return mid + 1; } function elementExists( ITornadoTreesV1 _tornadoTreesV1, string memory _type, uint256 index ) public view returns (bool success) { // Try to get the element. If it succeeds the array length is higher, it it reverts the length is equal or lower (success, ) = address(_tornadoTreesV1).staticcall{ gas: 2500 }(abi.encodeWithSignature(_type, index)); } function setTornadoProxyContract(address _tornadoProxy) external onlyGovernance { tornadoProxy = _tornadoProxy; emit ProxyUpdated(_tornadoProxy); } function setVerifierContract(IBatchTreeUpdateVerifier _treeUpdateVerifier) external onlyGovernance { treeUpdateVerifier = _treeUpdateVerifier; emit VerifierUpdated(address(_treeUpdateVerifier)); } function blockNumber() public view virtual returns (uint256) { return block.number; } }
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; /** * @dev TransparentUpgradeableProxy where admin is allowed to call implementation methods. */ contract AdminUpgradeableProxy is TransparentUpgradeableProxy { /** * @dev Initializes an upgradeable proxy backed by the implementation at `_logic`. */ constructor( address _logic, address _admin, bytes memory _data ) public payable TransparentUpgradeableProxy(_logic, _admin, _data) {} /** * @dev Override to allow admin access the fallback function. */ function _beforeFallback() internal override {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ITornadoInstance { function token() external view returns (address); function denomination() external view returns (uint256); function deposit(bytes32 commitment) external payable; function withdraw( bytes calldata proof, bytes32 root, bytes32 nullifierHash, address payable recipient, address payable relayer, uint256 fee, uint256 refund ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ENS { function resolver(bytes32 node) external view returns (Resolver); } interface Resolver { function addr(bytes32 node) external view returns (address); } contract EnsResolve { function resolve(bytes32 node) public view virtual returns (address) { ENS Registry = ENS( getChainId() == 1 ? 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e : 0x8595bFb0D940DfEDC98943FA8a907091203f25EE ); return Registry.resolver(node).addr(node); } function bulkResolve(bytes32[] memory domains) public view returns (address[] memory result) { result = new address[](domains.length); for (uint256 i = 0; i < domains.length; i++) { result[i] = resolve(domains[i]); } } function getChainId() internal pure returns (uint256) { uint256 chainId; assembly { chainId := chainid() } return chainId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ITornadoProxyV1 { function updateInstance(address _instance, bool _update) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./UpgradeableProxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. */ contract TransparentUpgradeableProxy is UpgradeableProxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}. */ constructor(address _logic, address admin_, bytes memory _data) public payable UpgradeableProxy(_logic, _data) { assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); _setAdmin(admin_); } /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. */ modifier ifAdmin() { if (msg.sender == _admin()) { _; } else { _fallback(); } } /** * @dev Returns the current admin. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function admin() external ifAdmin returns (address admin_) { admin_ = _admin(); } /** * @dev Returns the current implementation. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function implementation() external ifAdmin returns (address implementation_) { implementation_ = _implementation(); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. * * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. */ function changeAdmin(address newAdmin) external ifAdmin { require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address"); emit AdminChanged(_admin(), newAdmin); _setAdmin(newAdmin); } /** * @dev Upgrade the implementation of the proxy. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeTo(newImplementation); } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. */ function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { _upgradeTo(newImplementation); // solhint-disable-next-line avoid-low-level-calls (bool success,) = newImplementation.delegatecall(data); require(success); } /** * @dev Returns the current admin. */ function _admin() internal view returns (address adm) { bytes32 slot = _ADMIN_SLOT; // solhint-disable-next-line no-inline-assembly assembly { adm := sload(slot) } } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { bytes32 slot = _ADMIN_SLOT; // solhint-disable-next-line no-inline-assembly assembly { sstore(slot, newAdmin) } } /** * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. */ function _beforeFallback() internal override virtual { require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); super._beforeFallback(); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./Proxy.sol"; import "../utils/Address.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. * * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see * {TransparentUpgradeableProxy}. */ contract UpgradeableProxy is Proxy { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializating the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) public payable { assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); _setImplementation(_logic); if(_data.length > 0) { // solhint-disable-next-line avoid-low-level-calls (bool success,) = _logic.delegatecall(_data); require(success); } } /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _implementation() internal override view returns (address impl) { bytes32 slot = _IMPLEMENTATION_SLOT; // solhint-disable-next-line no-inline-assembly assembly { impl := sload(slot) } } /** * @dev Upgrades the proxy to a new implementation. * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract"); bytes32 slot = _IMPLEMENTATION_SLOT; // solhint-disable-next-line no-inline-assembly assembly { sstore(slot, newImplementation) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _delegate(address implementation) internal { // solhint-disable-next-line no-inline-assembly assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal virtual view returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _fallback() internal { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback () external payable { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive () external payable { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overriden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual { } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ITornadoTrees { function registerDeposit(address instance, bytes32 commitment) external; function registerWithdrawal(address instance, bytes32 nullifier) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_tornadoTrees","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"components":[{"internalType":"contract ITornadoInstance","name":"addr","type":"address"},{"components":[{"internalType":"bool","name":"isERC20","type":"bool"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TornadoProxy.InstanceState","name":"state","type":"uint8"}],"internalType":"struct TornadoProxy.Instance","name":"instance","type":"tuple"}],"internalType":"struct TornadoProxy.Tornado[]","name":"_instances","type":"tuple[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"encryptedNote","type":"bytes"}],"name":"EncryptedNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ITornadoInstance","name":"instance","type":"address"},{"indexed":false,"internalType":"enum TornadoProxy.InstanceState","name":"state","type":"uint8"}],"name":"InstanceStateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ITornadoTrees","name":"addr","type":"address"}],"name":"TornadoTreesUpdated","type":"event"},{"inputs":[{"internalType":"bytes[]","name":"_encryptedNotes","type":"bytes[]"}],"name":"backupNotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITornadoInstance","name":"_tornado","type":"address"},{"internalType":"bytes32","name":"_commitment","type":"bytes32"},{"internalType":"bytes","name":"_encryptedNote","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ITornadoInstance","name":"","type":"address"}],"name":"instances","outputs":[{"internalType":"bool","name":"isERC20","type":"bool"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TornadoProxy.InstanceState","name":"state","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITornadoTrees","name":"_tornadoTrees","type":"address"}],"name":"setTornadoTreesContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tornadoTrees","outputs":[{"internalType":"contract ITornadoTrees","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract ITornadoInstance","name":"addr","type":"address"},{"components":[{"internalType":"bool","name":"isERC20","type":"bool"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TornadoProxy.InstanceState","name":"state","type":"uint8"}],"internalType":"struct TornadoProxy.Instance","name":"instance","type":"tuple"}],"internalType":"struct TornadoProxy.Tornado","name":"_tornado","type":"tuple"}],"name":"updateInstance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITornadoInstance","name":"_tornado","type":"address"},{"internalType":"bytes","name":"_proof","type":"bytes"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"bytes32","name":"_nullifierHash","type":"bytes32"},{"internalType":"address payable","name":"_recipient","type":"address"},{"internalType":"address payable","name":"_relayer","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_refund","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200213338038062002133833981016040819052620000349162000711565b600080546001600160a01b0319166001600160a01b038516178155606083901b6001600160601b0319166080525b81518110156200009a57620000918282815181106200007d57fe5b6020026020010151620000a460201b60201c565b60010162000062565b5050505062000aa2565b60208181015182516001600160a01b03908116600090815260018452604090819020835181549585015160ff1990961690151517610100600160a81b0319166101009590931694909402919091178084559082015191929190829060ff60a81b1916600160a81b8360028111156200011857fe5b02179055505050602081015151156200032957600081600001516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200016b57600080fd5b505afa15801562000180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001a69190620006f2565b90508160200151602001516001600160a01b0316816001600160a01b031614620001ed5760405162461bcd60e51b8152600401620001e49062000908565b60405180910390fd5b8151604051636eb1769f60e11b81526000916001600160a01b0384169163dd62ed3e91620002219130919060040162000845565b60206040518083038186803b1580156200023a57600080fd5b505afa1580156200024f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027591906200080e565b9050600083602001516040015160028111156200028e57fe5b141580156200029b575080155b15620002d257620002cc8360000151600019846001600160a01b03166200037b60201b6200090e179092919060201c565b62000326565b60008360200151604001516002811115620002e957fe5b148015620002f657508015155b1562000326576200032683600001516000846001600160a01b03166200037b60201b6200090e179092919060201c565b50505b80600001516001600160a01b03167f02826f62d88a4d9f1978eb9c06f8663f642d032908e65a915d5898f3585421c082602001516040015160405162000370919062000878565b60405180910390a250565b8015806200040a5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90620003b4903090869060040162000845565b60206040518083038186803b158015620003cd57600080fd5b505afa158015620003e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040891906200080e565b155b620004295760405162461bcd60e51b8152600401620001e490620009b2565b620004848363095ea7b360e01b84846040516024016200044b9291906200085f565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200048916565b505050565b6060620004e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200052560201b62000a08179092919060201c565b805190915015620004845780806020019051810190620005069190620007ec565b620004845760405162461bcd60e51b8152600401620001e49062000968565b606062000536848460008562000540565b90505b9392505050565b606082471015620005655760405162461bcd60e51b8152600401620001e490620008c2565b620005708562000610565b6200058f5760405162461bcd60e51b8152600401620001e49062000931565b60006060866001600160a01b03168587604051620005ae919062000827565b60006040518083038185875af1925050503d8060008114620005ed576040519150601f19603f3d011682016040523d82523d6000602084013e620005f2565b606091505b5090925090506200060582828662000616565b979650505050505050565b3b151590565b606083156200062757508162000539565b825115620006385782518084602001fd5b8160405162461bcd60e51b8152600401620001e491906200088d565b6000818303608081121562000667578182fd5b62000673604062000a0f565b91508251620006828162000a89565b82526060601f19820112156200069757600080fd5b50620006a4606062000a0f565b60208301518015158114620006b857600080fd5b81526040830151620006ca8162000a89565b6020820152606083015160038110620006e257600080fd5b6040820152602082015292915050565b60006020828403121562000704578081fd5b8151620005398162000a89565b60008060006060848603121562000726578182fd5b8351620007338162000a89565b80935050602080850151620007488162000a89565b60408601519093506001600160401b0381111562000764578283fd5b8501601f8101871362000775578283fd5b80516200078c620007868262000a36565b62000a0f565b818152838101908385016080808502860187018c1015620007ab578788fd5b8795505b84861015620007db57620007c48c8362000654565b8452600195909501949286019290810190620007af565b505080955050505050509250925092565b600060208284031215620007fe578081fd5b8151801515811462000539578182fd5b60006020828403121562000820578081fd5b5051919050565b600082516200083b81846020870162000a56565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60208101600383106200088757fe5b91905290565b6000602082528251806020840152620008ae81604085016020870162000a56565b601f01601f19169190910160400192915050565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600f908201526e24b731b7b93932b1ba103a37b5b2b760891b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6040518181016001600160401b038111828210171562000a2e57600080fd5b604052919050565b60006001600160401b0382111562000a4c578081fd5b5060209081020190565b60005b8381101562000a7357818101518382015260200162000a59565b8381111562000a83576000848401525b50505050565b6001600160a01b038116811462000a9f57600080fd5b50565b60805160601c61166462000acf6000398061044d528061068552806106e7528061087b52506116646000f3fe6080604052600436106100865760003560e01c80636485ba2a116100595780636485ba2a1461010f578063b438689f1461012f578063cc6dc66814610142578063cea9d26f14610162578063e2658c9c1461018257610086565b8063032bb4431461008b57806313d98d13146100c35780633cb837fd146100d85780635aa6e675146100fa575b600080fd5b34801561009757600080fd5b506100ab6100a6366004610fea565b6101a2565b6040516100ba9392919061126f565b60405180910390f35b6100d66100d1366004611006565b6101d2565b005b3480156100e457600080fd5b506100ed61043c565b6040516100ba9190611204565b34801561010657600080fd5b506100ed61044b565b34801561011b57600080fd5b506100d661012a366004610f1f565b61046f565b6100d661013d366004611060565b6104dd565b34801561014e57600080fd5b506100d661015d366004611101565b61067a565b34801561016e57600080fd5b506100d661017d366004610faa565b6106dc565b34801561018e57600080fd5b506100d661019d366004610fea565b610870565b60016020526000908152604090205460ff808216916001600160a01b0361010082041691600160a81b9091041683565b6101da610e9e565b6001600160a01b038086166000908152600160209081526040918290208251606081018452815460ff80821615158352610100820490961693820193909352939092840191600160a81b900416600281111561023257fe5b600281111561023d57fe5b905250905060008160400151600281111561025457fe5b141561027b5760405162461bcd60e51b8152600401610272906113c4565b60405180910390fd5b80511561030e5761030e3330876001600160a01b0316638bca6d166040518163ffffffff1660e01b815260040160206040518083038186803b1580156102c057600080fd5b505afa1580156102d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f891906111a6565b60208501516001600160a01b0316929190610a21565b60405163b214faa560e01b81526001600160a01b0386169063b214faa590349061033c90889060040161129f565b6000604051808303818588803b15801561035557600080fd5b505af1158015610369573d6000803e3d6000fd5b506002935061037792505050565b8160400151600281111561038757fe5b14156103f25760005460405163c6758d6b60e01b81526001600160a01b039091169063c6758d6b906103bf9088908890600401611256565b600060405180830381600087803b1580156103d957600080fd5b505af11580156103ed573d6000803e3d6000fd5b505050505b336001600160a01b03167ffa28df43db3553771f7209dcef046f3bdfea15870ab625dcda30ac58b82b4008848460405161042d9291906112a8565b60405180910390a25050505050565b6000546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60005b818110156104d857337ffa28df43db3553771f7209dcef046f3bdfea15870ab625dcda30ac58b82b40088484848181106104a857fe5b90506020028101906104ba9190611573565b6040516104c89291906112a8565b60405180910390a2600101610472565b505050565b6104e5610e9e565b6001600160a01b03808b166000908152600160209081526040918290208251606081018452815460ff80821615158352610100820490961693820193909352939092840191600160a81b900416600281111561053d57fe5b600281111561054857fe5b905250905060008160400151600281111561055f57fe5b141561057d5760405162461bcd60e51b8152600401610272906113c4565b6040516310d056db60e11b81526001600160a01b038b16906321a0adb69034906105b9908d908d908d908d908d908d908d908d906004016112bc565b6000604051808303818588803b1580156105d257600080fd5b505af11580156105e6573d6000803e3d6000fd5b50600293506105f492505050565b8160400151600281111561060457fe5b141561066e57600054604051620d70c960e51b81526001600160a01b03909116906301ae19209061063b908d908a90600401611256565b600060405180830381600087803b15801561065557600080fd5b505af1158015610669573d6000803e3d6000fd5b505050505b50505050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106c25760405162461bcd60e51b81526004016102729061154b565b6106d96106d436839003830183611118565b610a48565b50565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107245760405162461bcd60e51b81526004016102729061154b565b6001600160a01b03821661074a5760405162461bcd60e51b815260040161027290611432565b6001600160a01b0383166107a6574760006107658284610cda565b6040519091506001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561079e573d6000803e3d6000fd5b5050506104d8565b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906107d5903090600401611204565b60206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082591906111a6565b905060006108338284610cda565b9050600081116108555760405162461bcd60e51b8152600401610272906114be565b6108696001600160a01b0386168583610cf0565b5050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108b85760405162461bcd60e51b81526004016102729061154b565b600080546001600160a01b0319166001600160a01b0383161790556040517fd5ef75672982cb39cc849450302ce426d1655271003cae8a66cb533c12f86ecc90610903908390611204565b60405180910390a150565b8015806109965750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906109449030908690600401611218565b60206040518083038186803b15801561095c57600080fd5b505afa158015610970573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099491906111a6565b155b6109b25760405162461bcd60e51b8152600401610272906114f5565b6104d88363095ea7b360e01b84846040516024016109d1929190611256565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d0f565b6060610a178484600085610d9e565b90505b9392505050565b610a42846323b872dd60e01b8585856040516024016109d193929190611232565b50505050565b60208181015182516001600160a01b03908116600090815260018452604090819020835181549585015160ff1990961690151517610100600160a81b0319166101009590931694909402919091178084559082015191929190829060ff60a81b1916600160a81b836002811115610abb57fe5b0217905550505060208101515115610c8a57600081600001516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0c57600080fd5b505afa158015610b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b449190610f03565b90508160200151602001516001600160a01b0316816001600160a01b031614610b7f5760405162461bcd60e51b81526004016102729061139b565b8151604051636eb1769f60e11b81526000916001600160a01b0384169163dd62ed3e91610bb191309190600401611218565b60206040518083038186803b158015610bc957600080fd5b505afa158015610bdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0191906111a6565b905060008360200151604001516002811115610c1957fe5b14158015610c25575080155b15610c48578251610c43906001600160a01b0384169060001961090e565b610c87565b60008360200151604001516002811115610c5e57fe5b148015610c6a57508015155b15610c87578251610c87906001600160a01b03841690600061090e565b50505b80600001516001600160a01b03167f02826f62d88a4d9f1978eb9c06f8663f642d032908e65a915d5898f3585421c0826020015160400151604051610ccf919061130e565b60405180910390a250565b6000818310610ce95781610a1a565b5090919050565b6104d88363a9059cbb60e01b84846040516024016109d1929190611256565b6060610d64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a089092919063ffffffff16565b8051909150156104d85780806020019051810190610d829190610f8e565b6104d85760405162461bcd60e51b815260040161027290611474565b606082471015610dc05760405162461bcd60e51b815260040161027290611355565b610dc985610e5f565b610de55760405162461bcd60e51b8152600401610272906113fb565b60006060866001600160a01b03168587604051610e0291906111e8565b60006040518083038185875af1925050503d8060008114610e3f576040519150601f19603f3d011682016040523d82523d6000602084013e610e44565b606091505b5091509150610e54828286610e65565b979650505050505050565b3b151590565b60608315610e74575081610a1a565b825115610e845782518084602001fd5b8160405162461bcd60e51b81526004016102729190611322565b60408051606081018252600080825260208201819052909182015290565b60008083601f840112610ecd578182fd5b50813567ffffffffffffffff811115610ee4578182fd5b602083019150836020828501011115610efc57600080fd5b9250929050565b600060208284031215610f14578081fd5b8151610a1a8161160b565b60008060208385031215610f31578081fd5b823567ffffffffffffffff80821115610f48578283fd5b818501915085601f830112610f5b578283fd5b813581811115610f69578384fd5b8660208083028501011115610f7c578384fd5b60209290920196919550909350505050565b600060208284031215610f9f578081fd5b8151610a1a81611620565b600080600060608486031215610fbe578081fd5b8335610fc98161160b565b92506020840135610fd98161160b565b929592945050506040919091013590565b600060208284031215610ffb578081fd5b8135610a1a8161160b565b6000806000806060858703121561101b578081fd5b84356110268161160b565b935060208501359250604085013567ffffffffffffffff811115611048578182fd5b61105487828801610ebc565b95989497509550505050565b60008060008060008060008060006101008a8c03121561107e578485fd5b89356110898161160b565b985060208a013567ffffffffffffffff8111156110a4578586fd5b6110b08c828d01610ebc565b90995097505060408a0135955060608a0135945060808a01356110d28161160b565b935060a08a01356110e28161160b565b8093505060c08a0135915060e08a013590509295985092959850929598565b600060808284031215611112578081fd5b50919050565b6000818303608081121561112a578182fd5b61113460406115b8565b833561113f8161160b565b81526060601f1983011215611152578283fd5b61115c60606115b8565b9150602084013561116c81611620565b8252604084013561117c8161160b565b6020830152606084013560038110611192578384fd5b604083015260208101919091529392505050565b6000602082840312156111b7578081fd5b5051919050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600082516111fa8184602087016115df565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b83151581526001600160a01b0383166020820152606081016003831061129157fe5b826040830152949350505050565b90815260200190565b600060208252610a176020830184866111be565b600060e082526112d060e083018a8c6111be565b60208301989098525060408101959095526001600160a01b03938416606086015291909216608084015260a083019190915260c09091015292915050565b602081016003831061131c57fe5b91905290565b60006020825282518060208401526113418160408501602087016115df565b601f01601f19169190910160400192915050565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600f908201526e24b731b7b93932b1ba103a37b5b2b760891b604082015260600190565b6020808252601d908201527f54686520696e7374616e6365206973206e6f7420737570706f72746564000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526022908201527f544f524e3a2063616e206e6f742073656e6420746f207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601e908201527f544f524e3a20747279696e6720746f2073656e6420302062616c616e63650000604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6000808335601e19843603018112611589578283fd5b83018035915067ffffffffffffffff8211156115a3578283fd5b602001915036819003821315610efc57600080fd5b60405181810167ffffffffffffffff811182821017156115d757600080fd5b604052919050565b60005b838110156115fa5781810151838201526020016115e2565b83811115610a425750506000910152565b6001600160a01b03811681146106d957600080fd5b80151581146106d957600080fdfea26469706673582212200d719f32b2430a348f95724be2ceff12a3b454612687bf8afd5a901af033526564736f6c634300060c0033000000000000000000000000527653ea119f3e6a1f5bd18fbf4714081d7b31ce0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001300000000000000000000000012d66f87a04a9e220743712ce6d9bb1b5616b8fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000047ce0c6ed5b0ce3d3a51fdb1c52dc66a7c3c2936000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000910cbd523d972eb0a6f4cae4618ad62622b39dbf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a160cdab225685da1d56aa342ad8841c3b53f291000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d4b88df4d29f5cedd6857912842cff3b20c8cfa300000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fd8610d20aa15b7b2e3be39b396a1bc3516c714400000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000007687e702b410fa43f4cb4af7fa097918ffd273000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000023773e65ed146a459791799d01336db287f2533400000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000022aaa7720ddd5388a3c0a3333430953c68f1849b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643000000000000000000000000000000000000000000000000000000000000000100000000000000000000000003893a7c7463ae47d46bc7f091665f189365600300000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e364300000000000000000000000000000000000000000000000000000000000000010000000000000000000000002717c5e28cf931547b621a5dddb772ab6a35b70100000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e36430000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d21be7248e0197ee08e0c20d4a96debdac3d20af00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e36430000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d96f2b1c14db8458374d9aca76e26c3d183643070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000004736dcf1b7a3d580672cce6e7c65cd5cc9cfba9d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000169ad27a470d064dede56a2d3ff727986b15d52b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000836222f2b2b24a3f36f98668ed8f0b38d1a872f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000178169b423a011fff22b9e3f3abea13414ddd0f100000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000610b717796ad172b316836ac95a2ffad065ceab400000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb93e510bbcd0b7beb5a853875f9ec60275cf49800000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x6080604052600436106100865760003560e01c80636485ba2a116100595780636485ba2a1461010f578063b438689f1461012f578063cc6dc66814610142578063cea9d26f14610162578063e2658c9c1461018257610086565b8063032bb4431461008b57806313d98d13146100c35780633cb837fd146100d85780635aa6e675146100fa575b600080fd5b34801561009757600080fd5b506100ab6100a6366004610fea565b6101a2565b6040516100ba9392919061126f565b60405180910390f35b6100d66100d1366004611006565b6101d2565b005b3480156100e457600080fd5b506100ed61043c565b6040516100ba9190611204565b34801561010657600080fd5b506100ed61044b565b34801561011b57600080fd5b506100d661012a366004610f1f565b61046f565b6100d661013d366004611060565b6104dd565b34801561014e57600080fd5b506100d661015d366004611101565b61067a565b34801561016e57600080fd5b506100d661017d366004610faa565b6106dc565b34801561018e57600080fd5b506100d661019d366004610fea565b610870565b60016020526000908152604090205460ff808216916001600160a01b0361010082041691600160a81b9091041683565b6101da610e9e565b6001600160a01b038086166000908152600160209081526040918290208251606081018452815460ff80821615158352610100820490961693820193909352939092840191600160a81b900416600281111561023257fe5b600281111561023d57fe5b905250905060008160400151600281111561025457fe5b141561027b5760405162461bcd60e51b8152600401610272906113c4565b60405180910390fd5b80511561030e5761030e3330876001600160a01b0316638bca6d166040518163ffffffff1660e01b815260040160206040518083038186803b1580156102c057600080fd5b505afa1580156102d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f891906111a6565b60208501516001600160a01b0316929190610a21565b60405163b214faa560e01b81526001600160a01b0386169063b214faa590349061033c90889060040161129f565b6000604051808303818588803b15801561035557600080fd5b505af1158015610369573d6000803e3d6000fd5b506002935061037792505050565b8160400151600281111561038757fe5b14156103f25760005460405163c6758d6b60e01b81526001600160a01b039091169063c6758d6b906103bf9088908890600401611256565b600060405180830381600087803b1580156103d957600080fd5b505af11580156103ed573d6000803e3d6000fd5b505050505b336001600160a01b03167ffa28df43db3553771f7209dcef046f3bdfea15870ab625dcda30ac58b82b4008848460405161042d9291906112a8565b60405180910390a25050505050565b6000546001600160a01b031681565b7f0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce81565b60005b818110156104d857337ffa28df43db3553771f7209dcef046f3bdfea15870ab625dcda30ac58b82b40088484848181106104a857fe5b90506020028101906104ba9190611573565b6040516104c89291906112a8565b60405180910390a2600101610472565b505050565b6104e5610e9e565b6001600160a01b03808b166000908152600160209081526040918290208251606081018452815460ff80821615158352610100820490961693820193909352939092840191600160a81b900416600281111561053d57fe5b600281111561054857fe5b905250905060008160400151600281111561055f57fe5b141561057d5760405162461bcd60e51b8152600401610272906113c4565b6040516310d056db60e11b81526001600160a01b038b16906321a0adb69034906105b9908d908d908d908d908d908d908d908d906004016112bc565b6000604051808303818588803b1580156105d257600080fd5b505af11580156105e6573d6000803e3d6000fd5b50600293506105f492505050565b8160400151600281111561060457fe5b141561066e57600054604051620d70c960e51b81526001600160a01b03909116906301ae19209061063b908d908a90600401611256565b600060405180830381600087803b15801561065557600080fd5b505af1158015610669573d6000803e3d6000fd5b505050505b50505050505050505050565b336001600160a01b037f0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce16146106c25760405162461bcd60e51b81526004016102729061154b565b6106d96106d436839003830183611118565b610a48565b50565b336001600160a01b037f0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce16146107245760405162461bcd60e51b81526004016102729061154b565b6001600160a01b03821661074a5760405162461bcd60e51b815260040161027290611432565b6001600160a01b0383166107a6574760006107658284610cda565b6040519091506001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561079e573d6000803e3d6000fd5b5050506104d8565b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906107d5903090600401611204565b60206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082591906111a6565b905060006108338284610cda565b9050600081116108555760405162461bcd60e51b8152600401610272906114be565b6108696001600160a01b0386168583610cf0565b5050505050565b336001600160a01b037f0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce16146108b85760405162461bcd60e51b81526004016102729061154b565b600080546001600160a01b0319166001600160a01b0383161790556040517fd5ef75672982cb39cc849450302ce426d1655271003cae8a66cb533c12f86ecc90610903908390611204565b60405180910390a150565b8015806109965750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906109449030908690600401611218565b60206040518083038186803b15801561095c57600080fd5b505afa158015610970573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099491906111a6565b155b6109b25760405162461bcd60e51b8152600401610272906114f5565b6104d88363095ea7b360e01b84846040516024016109d1929190611256565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d0f565b6060610a178484600085610d9e565b90505b9392505050565b610a42846323b872dd60e01b8585856040516024016109d193929190611232565b50505050565b60208181015182516001600160a01b03908116600090815260018452604090819020835181549585015160ff1990961690151517610100600160a81b0319166101009590931694909402919091178084559082015191929190829060ff60a81b1916600160a81b836002811115610abb57fe5b0217905550505060208101515115610c8a57600081600001516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0c57600080fd5b505afa158015610b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b449190610f03565b90508160200151602001516001600160a01b0316816001600160a01b031614610b7f5760405162461bcd60e51b81526004016102729061139b565b8151604051636eb1769f60e11b81526000916001600160a01b0384169163dd62ed3e91610bb191309190600401611218565b60206040518083038186803b158015610bc957600080fd5b505afa158015610bdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0191906111a6565b905060008360200151604001516002811115610c1957fe5b14158015610c25575080155b15610c48578251610c43906001600160a01b0384169060001961090e565b610c87565b60008360200151604001516002811115610c5e57fe5b148015610c6a57508015155b15610c87578251610c87906001600160a01b03841690600061090e565b50505b80600001516001600160a01b03167f02826f62d88a4d9f1978eb9c06f8663f642d032908e65a915d5898f3585421c0826020015160400151604051610ccf919061130e565b60405180910390a250565b6000818310610ce95781610a1a565b5090919050565b6104d88363a9059cbb60e01b84846040516024016109d1929190611256565b6060610d64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a089092919063ffffffff16565b8051909150156104d85780806020019051810190610d829190610f8e565b6104d85760405162461bcd60e51b815260040161027290611474565b606082471015610dc05760405162461bcd60e51b815260040161027290611355565b610dc985610e5f565b610de55760405162461bcd60e51b8152600401610272906113fb565b60006060866001600160a01b03168587604051610e0291906111e8565b60006040518083038185875af1925050503d8060008114610e3f576040519150601f19603f3d011682016040523d82523d6000602084013e610e44565b606091505b5091509150610e54828286610e65565b979650505050505050565b3b151590565b60608315610e74575081610a1a565b825115610e845782518084602001fd5b8160405162461bcd60e51b81526004016102729190611322565b60408051606081018252600080825260208201819052909182015290565b60008083601f840112610ecd578182fd5b50813567ffffffffffffffff811115610ee4578182fd5b602083019150836020828501011115610efc57600080fd5b9250929050565b600060208284031215610f14578081fd5b8151610a1a8161160b565b60008060208385031215610f31578081fd5b823567ffffffffffffffff80821115610f48578283fd5b818501915085601f830112610f5b578283fd5b813581811115610f69578384fd5b8660208083028501011115610f7c578384fd5b60209290920196919550909350505050565b600060208284031215610f9f578081fd5b8151610a1a81611620565b600080600060608486031215610fbe578081fd5b8335610fc98161160b565b92506020840135610fd98161160b565b929592945050506040919091013590565b600060208284031215610ffb578081fd5b8135610a1a8161160b565b6000806000806060858703121561101b578081fd5b84356110268161160b565b935060208501359250604085013567ffffffffffffffff811115611048578182fd5b61105487828801610ebc565b95989497509550505050565b60008060008060008060008060006101008a8c03121561107e578485fd5b89356110898161160b565b985060208a013567ffffffffffffffff8111156110a4578586fd5b6110b08c828d01610ebc565b90995097505060408a0135955060608a0135945060808a01356110d28161160b565b935060a08a01356110e28161160b565b8093505060c08a0135915060e08a013590509295985092959850929598565b600060808284031215611112578081fd5b50919050565b6000818303608081121561112a578182fd5b61113460406115b8565b833561113f8161160b565b81526060601f1983011215611152578283fd5b61115c60606115b8565b9150602084013561116c81611620565b8252604084013561117c8161160b565b6020830152606084013560038110611192578384fd5b604083015260208101919091529392505050565b6000602082840312156111b7578081fd5b5051919050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600082516111fa8184602087016115df565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b83151581526001600160a01b0383166020820152606081016003831061129157fe5b826040830152949350505050565b90815260200190565b600060208252610a176020830184866111be565b600060e082526112d060e083018a8c6111be565b60208301989098525060408101959095526001600160a01b03938416606086015291909216608084015260a083019190915260c09091015292915050565b602081016003831061131c57fe5b91905290565b60006020825282518060208401526113418160408501602087016115df565b601f01601f19169190910160400192915050565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600f908201526e24b731b7b93932b1ba103a37b5b2b760891b604082015260600190565b6020808252601d908201527f54686520696e7374616e6365206973206e6f7420737570706f72746564000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526022908201527f544f524e3a2063616e206e6f742073656e6420746f207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601e908201527f544f524e3a20747279696e6720746f2073656e6420302062616c616e63650000604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6000808335601e19843603018112611589578283fd5b83018035915067ffffffffffffffff8211156115a3578283fd5b602001915036819003821315610efc57600080fd5b60405181810167ffffffffffffffff811182821017156115d757600080fd5b604052919050565b60005b838110156115fa5781810151838201526020016115e2565b83811115610a425750506000910152565b6001600160a01b03811681146106d957600080fd5b80151581146106d957600080fdfea26469706673582212200d719f32b2430a348f95724be2ceff12a3b454612687bf8afd5a901af033526564736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000527653ea119f3e6a1f5bd18fbf4714081d7b31ce0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001300000000000000000000000012d66f87a04a9e220743712ce6d9bb1b5616b8fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000047ce0c6ed5b0ce3d3a51fdb1c52dc66a7c3c2936000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000910cbd523d972eb0a6f4cae4618ad62622b39dbf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a160cdab225685da1d56aa342ad8841c3b53f291000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d4b88df4d29f5cedd6857912842cff3b20c8cfa300000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fd8610d20aa15b7b2e3be39b396a1bc3516c714400000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000007687e702b410fa43f4cb4af7fa097918ffd273000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000023773e65ed146a459791799d01336db287f2533400000000000000000000000000000000000000000000000000000000000000010000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000022aaa7720ddd5388a3c0a3333430953c68f1849b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643000000000000000000000000000000000000000000000000000000000000000100000000000000000000000003893a7c7463ae47d46bc7f091665f189365600300000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e364300000000000000000000000000000000000000000000000000000000000000010000000000000000000000002717c5e28cf931547b621a5dddb772ab6a35b70100000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e36430000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d21be7248e0197ee08e0c20d4a96debdac3d20af00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e36430000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d96f2b1c14db8458374d9aca76e26c3d183643070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000004736dcf1b7a3d580672cce6e7c65cd5cc9cfba9d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000169ad27a470d064dede56a2d3ff727986b15d52b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000836222f2b2b24a3f36f98668ed8f0b38d1a872f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000178169b423a011fff22b9e3f3abea13414ddd0f100000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000610b717796ad172b316836ac95a2ffad065ceab400000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb93e510bbcd0b7beb5a853875f9ec60275cf49800000000000000000000000000000000000000000000000000000000000000010000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _tornadoTrees (address): 0x527653eA119F3E6a1F5BD18fbF4714081D7B31ce
Arg [1] : _governance (address): 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce
Arg [2] : _instances (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
80 Constructor Arguments found :
Arg [0] : 000000000000000000000000527653ea119f3e6a1f5bd18fbf4714081d7b31ce
Arg [1] : 0000000000000000000000005efda50f22d34f262c29268506c5fa42cb56a1ce
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [4] : 00000000000000000000000012d66f87a04a9e220743712ce6d9bb1b5616b8fc
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 00000000000000000000000047ce0c6ed5b0ce3d3a51fdb1c52dc66a7c3c2936
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 000000000000000000000000910cbd523d972eb0a6f4cae4618ad62622b39dbf
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [16] : 000000000000000000000000a160cdab225685da1d56aa342ad8841c3b53f291
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [20] : 000000000000000000000000d4b88df4d29f5cedd6857912842cff3b20c8cfa3
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [22] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [24] : 000000000000000000000000fd8610d20aa15b7b2e3be39b396a1bc3516c7144
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [26] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [28] : 00000000000000000000000007687e702b410fa43f4cb4af7fa097918ffd2730
Arg [29] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [30] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [32] : 00000000000000000000000023773e65ed146a459791799d01336db287f25334
Arg [33] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [34] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [35] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [36] : 00000000000000000000000022aaa7720ddd5388a3c0a3333430953c68f1849b
Arg [37] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [38] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Arg [39] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [40] : 00000000000000000000000003893a7c7463ae47d46bc7f091665f1893656003
Arg [41] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [42] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Arg [43] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [44] : 0000000000000000000000002717c5e28cf931547b621a5dddb772ab6a35b701
Arg [45] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [46] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Arg [47] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [48] : 000000000000000000000000d21be7248e0197ee08e0c20d4a96debdac3d20af
Arg [49] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [50] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Arg [51] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [52] : 000000000000000000000000d96f2b1c14db8458374d9aca76e26c3d18364307
Arg [53] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [54] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [55] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [56] : 0000000000000000000000004736dcf1b7a3d580672cce6e7c65cd5cc9cfba9d
Arg [57] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [58] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [59] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [60] : 000000000000000000000000169ad27a470d064dede56a2d3ff727986b15d52b
Arg [61] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [62] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [63] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [64] : 0000000000000000000000000836222f2b2b24a3f36f98668ed8f0b38d1a872f
Arg [65] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [66] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [67] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [68] : 000000000000000000000000178169b423a011fff22b9e3f3abea13414ddd0f1
Arg [69] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [70] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [71] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [72] : 000000000000000000000000610b717796ad172b316836ac95a2ffad065ceab4
Arg [73] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [74] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [75] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [76] : 000000000000000000000000bb93e510bbcd0b7beb5a853875f9ec60275cf498
Arg [77] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [78] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [79] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 100.00% | $623.05 | 0.00002 | $0.012461 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.