bc7fa5e887
Signed-off-by: T-Hax <>
143 lines
4.9 KiB
Solidity
143 lines
4.9 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
|
|
pragma solidity 0.7.6;
|
|
pragma abicoder v2;
|
|
|
|
// OZ Imports
|
|
|
|
import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
|
|
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
|
|
import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
|
|
|
|
// Local imports
|
|
|
|
import "./instances/ERC20TornadoCloneable.sol";
|
|
import "./instances/ETHTornadoCloneable.sol";
|
|
|
|
/**
|
|
* @title MinimalInstanceFactory
|
|
* @author AlienTornadosaurusHex
|
|
* @notice A factory to deploy new Tornado Instances.
|
|
*/
|
|
contract MinimalInstanceFactory {
|
|
using Clones for address;
|
|
using Address for address;
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/** @notice The address of the verifier contract, no actual use in the contract but just to show which
|
|
address was set in the instances */
|
|
address public immutable verifier;
|
|
|
|
/** @notice The address of the hasher contract, no actual use in the contract but just to show which address
|
|
was set in the instances */
|
|
address public immutable hasher;
|
|
|
|
/** @notice The address of the router which will have relayers run their txs through */
|
|
address public immutable router;
|
|
|
|
/** @notice The standard merkle tree height used for the instances */
|
|
uint32 public immutable merkleTreeHeight;
|
|
|
|
/** @notice The implementation which will be used for the cloned ETH (!) instances */
|
|
address public immutable ethImpl;
|
|
|
|
/** @notice The implementation which will be used for the cloned ERC20 (!) instances */
|
|
address public immutable ERC20Impl;
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EVENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
event NewTreeHeightSet(uint32 indexed newTreeHeight);
|
|
event NewInstanceCloneCreated(address indexed clone);
|
|
event NewImplementationSet(
|
|
address indexed ERC20Impl,
|
|
address indexed ethImpl,
|
|
address verifier,
|
|
address hasher
|
|
);
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/**
|
|
* @notice This instance factory is designed to be always able to print new
|
|
tornado instances.
|
|
*/
|
|
constructor(
|
|
address _verifierAddress,
|
|
address _hasherAddress,
|
|
address _routerAddresss,
|
|
uint32 _merkleTreeHeight
|
|
) {
|
|
// Store instance parameters
|
|
verifier = _verifierAddress;
|
|
hasher = _hasherAddress;
|
|
merkleTreeHeight = _merkleTreeHeight;
|
|
|
|
// Store router addresses
|
|
router = _routerAddresss;
|
|
|
|
// Deploy implementations
|
|
ETHTornadoCloneable ethImplContract = new ETHTornadoCloneable(_verifierAddress, _hasherAddress);
|
|
ERC20TornadoCloneable ERC20ImplContract = new ERC20TornadoCloneable(_verifierAddress, _hasherAddress);
|
|
|
|
// Store implementations
|
|
ethImpl = address(ethImplContract);
|
|
ERC20Impl = address(ERC20ImplContract);
|
|
}
|
|
|
|
/**
|
|
* @notice Creates a new Tornado instance. If the registry is dead, you can
|
|
immediately call `relayerRegistryIsDead()` on the cloned instance.
|
|
* @param _denomination The denomination of the cloned instance. Must be in E18.
|
|
* @param _token The token address of the new instance.
|
|
then it will be ETH
|
|
*/
|
|
function createInstanceClone(uint256 _denomination, address _token) public virtual returns (address clone) {
|
|
// Calculate salt for the deterministic deployment
|
|
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
|
|
|
// Check whether token is ETH
|
|
if (_token == address(0)) {
|
|
// Calc deployment address
|
|
clone = ethImpl.predictDeterministicAddress(salt);
|
|
|
|
// Check whether already exists, if so, don't deploy, just give address
|
|
if (!clone.isContract()) {
|
|
ethImpl.cloneDeterministic(salt);
|
|
emit NewInstanceCloneCreated(clone);
|
|
ETHTornadoCloneable(clone).initialize(_denomination, merkleTreeHeight);
|
|
}
|
|
} else {
|
|
// Calc deployment address
|
|
clone = ERC20Impl.predictDeterministicAddress(salt);
|
|
|
|
// Check whether already exists, if so, don't deploy, just give address
|
|
if (!clone.isContract()) {
|
|
ERC20Impl.cloneDeterministic(salt);
|
|
emit NewInstanceCloneCreated(clone);
|
|
ERC20TornadoCloneable(clone).initialize(router, _token, _denomination, merkleTreeHeight);
|
|
}
|
|
}
|
|
|
|
// Return address of the clone
|
|
return clone;
|
|
}
|
|
|
|
/**
|
|
* @notice Since addresses are deterministic, this function fetches the
|
|
deterministic address to which an instance would be or is deployed, for a
|
|
specific denomination and token.
|
|
* @param _denomination The denomination to calculate the address for. Needs
|
|
to be E18.
|
|
* @param _token The token address to calculate the address for.
|
|
*/
|
|
function getInstanceAddress(uint256 _denomination, address _token) public view returns (address) {
|
|
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
|
if (_token == address(0)) {
|
|
return ethImpl.predictDeterministicAddress(salt);
|
|
} else {
|
|
return ERC20Impl.predictDeterministicAddress(salt);
|
|
}
|
|
}
|
|
}
|