tornado-pool-factory/contracts/InstanceFactory.sol

84 lines
2.8 KiB
Solidity

// 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 "./ERC20TornadoCloneable.sol";
contract InstanceFactory is Initializable {
using Clones for address;
using Address for address;
address public admin;
address public implementation;
address public verifier;
address public hasher;
uint32 public merkleTreeHeight;
event NewTreeHeightSet(uint32 indexed newTreeHeight);
event NewImplementationSet(address indexed newImplemenentation, address verifier, address hasher);
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
* */
function initialize(
address _verifier,
address _hasher,
uint32 _merkleTreeHeight,
address _admin
) public initializer {
verifier = _verifier;
hasher = _hasher;
merkleTreeHeight = _merkleTreeHeight;
admin = _admin;
ERC20TornadoCloneable implContract = new ERC20TornadoCloneable(_verifier, _hasher);
implementation = address(implContract);
}
/**
* @dev Creates new Tornado instance.
* @param _denomination denomination of new Tornado instance
* @param _token address of ERC20 token for a new instance
*/
function createInstanceClone(uint256 _denomination, address _token) public virtual returns (address) {
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
address newClone = implementation.predictDeterministicAddress(salt);
if (!newClone.isContract()) {
implementation.cloneDeterministic(salt);
emit NewInstanceCloneCreated(newClone);
ERC20TornadoCloneable(newClone).init(_denomination, merkleTreeHeight, _token);
}
return newClone;
}
function getInstanceAddress(uint256 _denomination, address _token) public view returns (address) {
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
return implementation.predictDeterministicAddress(salt);
}
function setMerkleTreeHeight(uint32 _merkleTreeHeight) external onlyAdmin {
merkleTreeHeight = _merkleTreeHeight;
emit NewTreeHeightSet(merkleTreeHeight);
}
function generateNewImplementation(address _verifier, address _hasher) external onlyAdmin {
verifier = _verifier;
hasher = _hasher;
implementation = address(new ERC20TornadoCloneable(_verifier, _hasher));
emit NewImplementationSet(implementation, _verifier, _hasher);
}
}