tornado-instances/contracts/MinimalInstanceFactory.sol

77 lines
2.8 KiB
Solidity
Raw Normal View History

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 MinimalInstanceFactory {
using Clones for address;
using Address for address;
address public immutable ERC20Impl;
address public immutable nativeCurImpl;
address public immutable verifier;
address public immutable hasher;
uint32 public immutable merkleTreeHeight;
event NewTreeHeightSet(uint32 indexed newTreeHeight);
event NewImplementationSet(address indexed ERC20Impl, address indexed nativeCurImpl, address verifier, address hasher);
event NewInstanceCloneCreated(address indexed clone);
/**
* @notice This instance factory is NOT permissioned. It is designed to always be able to print
* new Tornado Instances if necessary.
* @dev Creates new Tornado instance.
*/
constructor(address _verifier, address _hasher, uint32 _merkleTreeHeight) public {
verifier = _verifier;
hasher = _hasher;
merkleTreeHeight = _merkleTreeHeight;
ERC20TornadoCloneable ERC20ImplContract = new ERC20TornadoCloneable(_verifier, _hasher);
ERC20Impl = address(ERC20ImplContract);
ETHTornadoCloneable nativeCurImplContract = new ETHTornadoCloneable(_verifier, _hasher);
nativeCurImpl = address(nativeCurImplContract);
}
/**
* @notice 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
*/
function createInstanceClone(uint256 _denomination, address _token) public virtual 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);
}
}
}