instances/contracts/MinimalInstanceFactory.sol
T-Hax bc7fa5e887 deploy script fixup
Signed-off-by: T-Hax <>
2023-06-12 16:13:21 +00:00

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);
}
}
}