2023-04-08 21:43:42 +03:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
pragma solidity 0.7.6;
|
|
|
|
pragma abicoder v2;
|
|
|
|
|
|
|
|
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
|
|
|
|
import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
|
|
|
|
import "@openzeppelin/contracts/proxy/Clones.sol";
|
|
|
|
import "./instances/ERC20TornadoCloneable.sol";
|
|
|
|
import "./instances/ETHTornadoCloneable.sol";
|
|
|
|
|
|
|
|
contract InstanceFactory is Initializable {
|
|
|
|
using Clones for address;
|
|
|
|
using Address for address;
|
|
|
|
|
|
|
|
address public admin;
|
|
|
|
address public ERC20Impl;
|
|
|
|
address public nativeCurImpl;
|
|
|
|
address public verifier;
|
|
|
|
address public hasher;
|
|
|
|
uint32 public merkleTreeHeight;
|
|
|
|
|
|
|
|
event NewTreeHeightSet(uint32 indexed newTreeHeight);
|
2023-06-12 18:50:25 +03:00
|
|
|
event NewImplementationSet(
|
|
|
|
address indexed ERC20Impl,
|
|
|
|
address indexed nativeCurImpl,
|
|
|
|
address verifier,
|
|
|
|
address hasher
|
|
|
|
);
|
2023-04-08 21:43:42 +03:00
|
|
|
event NewInstanceCloneCreated(address indexed clone);
|
|
|
|
|
|
|
|
modifier onlyAdmin() {
|
|
|
|
require(admin == msg.sender, "IF: caller is not the admin");
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @notice initialize function for upgradeability
|
|
|
|
* @dev this contract will be deployed behind a proxy and should not assign values at logic address,
|
|
|
|
* params left out because self explainable
|
|
|
|
* */
|
2023-06-12 18:50:25 +03:00
|
|
|
function initialize(
|
|
|
|
address _verifier,
|
|
|
|
address _hasher,
|
|
|
|
uint32 _merkleTreeHeight,
|
|
|
|
address _admin,
|
|
|
|
address router
|
|
|
|
) public initializer {
|
2023-04-08 21:43:42 +03:00
|
|
|
verifier = _verifier;
|
|
|
|
hasher = _hasher;
|
|
|
|
merkleTreeHeight = _merkleTreeHeight;
|
|
|
|
admin = _admin;
|
|
|
|
|
|
|
|
ERC20TornadoCloneable ERC20ImplContract = new ERC20TornadoCloneable(_verifier, _hasher);
|
|
|
|
ERC20Impl = address(ERC20ImplContract);
|
|
|
|
ETHTornadoCloneable nativeCurImplContract = new ETHTornadoCloneable(_verifier, _hasher);
|
|
|
|
nativeCurImpl = address(nativeCurImplContract);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Creates new Tornado instance.
|
|
|
|
* @param _denomination denomination of new Tornado instance
|
|
|
|
* @param _token address of ERC20 token for a new instance, if zero address, then it will be ETH
|
|
|
|
*/
|
2023-06-12 18:50:25 +03:00
|
|
|
function createInstanceClone(
|
|
|
|
uint256 _denomination,
|
|
|
|
address _token
|
|
|
|
) public virtual onlyAdmin returns (address clone) {
|
2023-04-08 21:43:42 +03:00
|
|
|
return _createInstanceClone(_denomination, _token);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _createInstanceClone(uint256 _denomination, address _token) internal returns (address clone) {
|
|
|
|
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
|
|
|
|
|
|
|
if (_token == address(0)) {
|
|
|
|
clone = nativeCurImpl.predictDeterministicAddress(salt);
|
|
|
|
if (!clone.isContract()) {
|
|
|
|
nativeCurImpl.cloneDeterministic(salt);
|
|
|
|
emit NewInstanceCloneCreated(clone);
|
|
|
|
ETHTornadoCloneable(clone).init(_denomination, merkleTreeHeight);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
clone = ERC20Impl.predictDeterministicAddress(salt);
|
|
|
|
if (!clone.isContract()) {
|
|
|
|
ERC20Impl.cloneDeterministic(salt);
|
|
|
|
emit NewInstanceCloneCreated(clone);
|
|
|
|
ERC20TornadoCloneable(clone).init(_denomination, merkleTreeHeight, _token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getInstanceAddress(uint256 _denomination, address _token) public view returns (address) {
|
|
|
|
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
|
|
|
if (_token == address(0)) {
|
|
|
|
return nativeCurImpl.predictDeterministicAddress(salt);
|
|
|
|
} else {
|
|
|
|
return ERC20Impl.predictDeterministicAddress(salt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function setMerkleTreeHeight(uint32 _merkleTreeHeight) external onlyAdmin {
|
|
|
|
merkleTreeHeight = _merkleTreeHeight;
|
|
|
|
emit NewTreeHeightSet(merkleTreeHeight);
|
|
|
|
}
|
|
|
|
|
2023-06-12 18:50:25 +03:00
|
|
|
function generateNewImplementation(address _verifier, address _hasher, address _router) external onlyAdmin {
|
2023-04-08 21:43:42 +03:00
|
|
|
verifier = _verifier;
|
|
|
|
hasher = _hasher;
|
2023-06-12 18:50:25 +03:00
|
|
|
ERC20Impl = address(new ERC20TornadoCloneable(_verifier, _hasher, _router));
|
2023-04-08 21:43:42 +03:00
|
|
|
nativeCurImpl = address(new ETHTornadoCloneable(_verifier, _hasher));
|
|
|
|
emit NewImplementationSet(ERC20Impl, nativeCurImpl, _verifier, _hasher);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Transfers adminship of the contract to a new account (`newAdmin`).
|
|
|
|
* Can only be called by the current admin.
|
|
|
|
*/
|
|
|
|
function transferAdminship(address newAdmin) external onlyAdmin {
|
|
|
|
require(newAdmin != address(0), "IF: new owner is the zero address");
|
|
|
|
admin = newAdmin;
|
|
|
|
}
|
|
|
|
}
|