2022-03-09 22:43:57 +01:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
pragma solidity 0.7.6;
|
|
|
|
pragma abicoder v2;
|
|
|
|
|
|
|
|
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
|
|
|
|
import "./AddInstanceProposal.sol";
|
|
|
|
import "./InstanceFactory.sol";
|
|
|
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
|
|
import { IERC20Permit } from "@openzeppelin/contracts/drafts/IERC20Permit.sol";
|
2022-03-15 18:55:01 +01:00
|
|
|
import { IUniswapV3Factory } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
|
|
|
|
import { IUniswapV3PoolState } from "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol";
|
2022-03-09 22:43:57 +01:00
|
|
|
|
|
|
|
contract InstanceFactoryWithRegistry is InstanceFactory {
|
|
|
|
using Address for address;
|
|
|
|
|
|
|
|
address public immutable governance;
|
|
|
|
address public immutable torn;
|
|
|
|
address public immutable instanceRegistry;
|
2022-03-15 18:55:01 +01:00
|
|
|
IUniswapV3Factory public immutable UniswapV3Factory;
|
|
|
|
address public immutable WETH;
|
|
|
|
uint16 public TWAPSlotsMin;
|
2022-03-09 22:43:57 +01:00
|
|
|
uint256 public creationFee;
|
|
|
|
|
2022-03-15 18:55:01 +01:00
|
|
|
event NewCreationFeeSet(uint256 newCreationFee);
|
|
|
|
event NewTWAPSlotsMinSet(uint256 newTWAPSlotsMin);
|
2022-03-09 22:43:57 +01:00
|
|
|
event NewGovernanceProposalCreated(address indexed proposal);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Throws if called by any account other than the Governance.
|
|
|
|
*/
|
|
|
|
modifier onlyGovernance() {
|
2022-07-26 19:07:04 +02:00
|
|
|
require(governance == msg.sender, "IF: caller is not the Governance");
|
2022-03-09 22:43:57 +01:00
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
address _governance,
|
|
|
|
address _instanceRegistry,
|
|
|
|
address _torn,
|
2022-03-15 18:55:01 +01:00
|
|
|
address _UniswapV3Factory,
|
2022-07-26 19:07:04 +02:00
|
|
|
address _WETH
|
|
|
|
) {
|
2022-03-09 22:43:57 +01:00
|
|
|
governance = _governance;
|
|
|
|
instanceRegistry = _instanceRegistry;
|
|
|
|
torn = _torn;
|
2022-03-15 18:55:01 +01:00
|
|
|
UniswapV3Factory = IUniswapV3Factory(_UniswapV3Factory);
|
|
|
|
WETH = _WETH;
|
2022-07-26 19:07:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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 _governance,
|
|
|
|
uint16 _TWAPSlotsMin,
|
|
|
|
uint256 _creationFee
|
|
|
|
) external initializer {
|
|
|
|
initialize(_verifier, _hasher, _merkleTreeHeight, _governance);
|
2022-03-15 18:55:01 +01:00
|
|
|
TWAPSlotsMin = _TWAPSlotsMin;
|
2022-03-09 22:43:57 +01:00
|
|
|
creationFee = _creationFee;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-03-31 21:40:12 +02:00
|
|
|
* @dev Creates new Tornado instances. Throws if called by any account other than the Governance.
|
2022-03-09 22:43:57 +01:00
|
|
|
* @param _denomination denomination of new Tornado instance
|
|
|
|
* @param _token address of ERC20 token for a new instance
|
|
|
|
*/
|
|
|
|
function createInstanceClone(uint256 _denomination, address _token) public override onlyGovernance returns (address) {
|
|
|
|
return super.createInstanceClone(_denomination, _token);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Creates AddInstanceProposal with approve.
|
|
|
|
* @param _token address of ERC20 token for a new instance
|
|
|
|
* @param _uniswapPoolSwappingFee fee value of Uniswap instance which will be used for `TORN/token` price determination.
|
|
|
|
* `3000` means 0.3% fee Uniswap pool.
|
|
|
|
* @param _denominations list of denominations for each new instance
|
|
|
|
* @param _protocolFees list of protocol fees for each new instance.
|
|
|
|
* `100` means that instance withdrawal fee is 1% of denomination.
|
|
|
|
*/
|
|
|
|
function createProposalApprove(
|
|
|
|
address _token,
|
|
|
|
uint24 _uniswapPoolSwappingFee,
|
|
|
|
uint256[] memory _denominations,
|
|
|
|
uint32[] memory _protocolFees
|
|
|
|
) external returns (address) {
|
|
|
|
require(IERC20(torn).transferFrom(msg.sender, governance, creationFee));
|
|
|
|
return _createProposal(_token, _uniswapPoolSwappingFee, _denominations, _protocolFees);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Creates AddInstanceProposal with permit.
|
|
|
|
* @param _token address of ERC20 token for a new instance
|
|
|
|
* @param _uniswapPoolSwappingFee fee value of Uniswap instance which will be used for `TORN/token` price determination.
|
|
|
|
* `3000` means 0.3% fee Uniswap pool.
|
|
|
|
* @param _denominations list of denominations for each new instance
|
|
|
|
* @param _protocolFees list of protocol fees for each new instance.
|
|
|
|
* `100` means that instance withdrawal fee is 1% of denomination.
|
|
|
|
*/
|
|
|
|
function createProposalPermit(
|
|
|
|
address _token,
|
|
|
|
uint24 _uniswapPoolSwappingFee,
|
|
|
|
uint256[] memory _denominations,
|
|
|
|
uint32[] memory _protocolFees,
|
|
|
|
address creater,
|
|
|
|
uint256 deadline,
|
|
|
|
uint8 v,
|
|
|
|
bytes32 r,
|
|
|
|
bytes32 s
|
|
|
|
) external returns (address) {
|
|
|
|
IERC20Permit(torn).permit(creater, address(this), creationFee, deadline, v, r, s);
|
|
|
|
require(IERC20(torn).transferFrom(creater, governance, creationFee));
|
|
|
|
return _createProposal(_token, _uniswapPoolSwappingFee, _denominations, _protocolFees);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _createProposal(
|
|
|
|
address _token,
|
|
|
|
uint24 _uniswapPoolSwappingFee,
|
|
|
|
uint256[] memory _denominations,
|
|
|
|
uint32[] memory _protocolFees
|
|
|
|
) internal returns (address) {
|
|
|
|
require(_token.isContract(), "Token is not contract");
|
|
|
|
require(_denominations.length > 0, "Empty denominations");
|
|
|
|
require(_denominations.length == _protocolFees.length, "Incorrect denominations/fees length");
|
|
|
|
|
2022-03-15 18:55:01 +01:00
|
|
|
// check Uniswap Pool
|
|
|
|
for (uint8 i = 0; i < _protocolFees.length; i++) {
|
|
|
|
if (_protocolFees[i] > 0) {
|
2022-04-26 17:55:34 +02:00
|
|
|
require(_protocolFees[i] <= 10000, "Protocol fee is more than 100%");
|
2022-03-15 18:55:01 +01:00
|
|
|
// pool exists
|
|
|
|
address poolAddr = UniswapV3Factory.getPool(_token, WETH, _uniswapPoolSwappingFee);
|
|
|
|
require(poolAddr != address(0), "Uniswap pool is not exist");
|
|
|
|
// TWAP slots
|
|
|
|
(, , , , uint16 observationCardinalityNext, , ) = IUniswapV3PoolState(poolAddr).slot0();
|
|
|
|
require(observationCardinalityNext >= TWAPSlotsMin, "Uniswap pool TWAP slots number is low");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:43:57 +01:00
|
|
|
address proposal = address(
|
|
|
|
new AddInstanceProposal(address(this), instanceRegistry, _token, _uniswapPoolSwappingFee, _denominations, _protocolFees)
|
|
|
|
);
|
|
|
|
emit NewGovernanceProposalCreated(proposal);
|
|
|
|
|
|
|
|
return proposal;
|
|
|
|
}
|
|
|
|
|
2022-07-26 19:07:04 +02:00
|
|
|
function setCreationFee(uint256 _creationFee) external onlyAdmin {
|
2022-03-09 22:43:57 +01:00
|
|
|
creationFee = _creationFee;
|
|
|
|
emit NewCreationFeeSet(_creationFee);
|
|
|
|
}
|
2022-03-15 18:55:01 +01:00
|
|
|
|
2022-07-26 19:07:04 +02:00
|
|
|
function setTWAPSlotsMin(uint16 _TWAPSlotsMin) external onlyAdmin {
|
2022-03-15 18:55:01 +01:00
|
|
|
TWAPSlotsMin = _TWAPSlotsMin;
|
|
|
|
emit NewTWAPSlotsMinSet(_TWAPSlotsMin);
|
|
|
|
}
|
2022-03-09 22:43:57 +01:00
|
|
|
}
|