mirror of
https://github.com/tornadocash/tornado-pool-factory
synced 2024-02-02 15:04:08 +01:00
add uniswap pool check
This commit is contained in:
parent
65a01c3ce8
commit
9bfbc01d8e
@ -29,6 +29,7 @@ Anyone can create governance proposal for the addition of a new ERC20 instance b
|
|||||||
|
|
||||||
1. `max number of new instances in one proposal` - the current version supports the addition of a maximum of 4 instances at once.
|
1. `max number of new instances in one proposal` - the current version supports the addition of a maximum of 4 instances at once.
|
||||||
2. `proposal creation fee` - this fee is charged from creator of proposal during `createProposalApprove/createProposalPermit` factory method execution. It can be changed by governance. Default value is stored in `config.js`.
|
2. `proposal creation fee` - this fee is charged from creator of proposal during `createProposalApprove/createProposalPermit` factory method execution. It can be changed by governance. Default value is stored in `config.js`.
|
||||||
|
3. `TWAPSlotsMin` - minimum number of TWAP slots for Uniswap pool that is chosen during `createProposalApprove/createProposalPermit` factory method call. It can be changed by governance. Default value is stored in `config.js`.
|
||||||
|
|
||||||
## Warnings
|
## Warnings
|
||||||
|
|
||||||
@ -60,8 +61,8 @@ Check config.js for actual values.
|
|||||||
|
|
||||||
With `salt` = `0x0000000000000000000000000000000000000000000000000000000047941987` address must be:
|
With `salt` = `0x0000000000000000000000000000000000000000000000000000000047941987` address must be:
|
||||||
|
|
||||||
1. `InstanceFactory` - `0x9A04e3F1091A69CB53D163abE7ad9bbc86C23823`
|
1. `InstanceFactory` - `0x09110e04d5AEF747bcf7A3585D8FFC892Ab9D1Cf`
|
||||||
1. `InstanceFactoryWithRegistry` - `0xee994E045B9Ec5a37f3f85d34f9fD087A0c69236`
|
2. `InstanceFactoryWithRegistry` - `0xC01D57d83E9Fe35E0Fb900F9D384EFcA679DF4bD`
|
||||||
|
|
||||||
Check addresses with current config:
|
Check addresses with current config:
|
||||||
|
|
||||||
|
@ -15,4 +15,7 @@ module.exports = {
|
|||||||
creationFee: '200000000000000000000', // 200 TORN
|
creationFee: '200000000000000000000', // 200 TORN
|
||||||
deployGasLimit: 7000000,
|
deployGasLimit: 7000000,
|
||||||
owner: '0xBAE5aBfa98466Dbe68836763B087f2d189f4D28f',
|
owner: '0xBAE5aBfa98466Dbe68836763B087f2d189f4D28f',
|
||||||
|
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
||||||
|
UniswapV3Factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||||
|
TWAPSlotsMin: 50,
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ contract AddInstanceProposal {
|
|||||||
token = _token;
|
token = _token;
|
||||||
uniswapPoolSwappingFee = _uniswapPoolSwappingFee;
|
uniswapPoolSwappingFee = _uniswapPoolSwappingFee;
|
||||||
|
|
||||||
require(_denominations.length == _protocolFees.length, "denominations length != protocolFees length");
|
require(_denominations.length == _protocolFees.length, "Incorrect denominations/fees length");
|
||||||
uint256 _numInstances = _denominations.length;
|
uint256 _numInstances = _denominations.length;
|
||||||
require(_numInstances > 0 && _numInstances <= 4, "incorrect instances number");
|
require(_numInstances > 0 && _numInstances <= 4, "incorrect instances number");
|
||||||
numInstances = _numInstances;
|
numInstances = _numInstances;
|
||||||
|
@ -8,6 +8,8 @@ import "./AddInstanceProposal.sol";
|
|||||||
import "./InstanceFactory.sol";
|
import "./InstanceFactory.sol";
|
||||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import { IERC20Permit } from "@openzeppelin/contracts/drafts/IERC20Permit.sol";
|
import { IERC20Permit } from "@openzeppelin/contracts/drafts/IERC20Permit.sol";
|
||||||
|
import { IUniswapV3Factory } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
|
||||||
|
import { IUniswapV3PoolState } from "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol";
|
||||||
|
|
||||||
contract InstanceFactoryWithRegistry is InstanceFactory {
|
contract InstanceFactoryWithRegistry is InstanceFactory {
|
||||||
using Address for address;
|
using Address for address;
|
||||||
@ -15,9 +17,13 @@ contract InstanceFactoryWithRegistry is InstanceFactory {
|
|||||||
address public immutable governance;
|
address public immutable governance;
|
||||||
address public immutable torn;
|
address public immutable torn;
|
||||||
address public immutable instanceRegistry;
|
address public immutable instanceRegistry;
|
||||||
|
IUniswapV3Factory public immutable UniswapV3Factory;
|
||||||
|
address public immutable WETH;
|
||||||
|
uint16 public TWAPSlotsMin;
|
||||||
uint256 public creationFee;
|
uint256 public creationFee;
|
||||||
|
|
||||||
event NewCreationFeeSet(uint256 indexed newCreationFee);
|
event NewCreationFeeSet(uint256 newCreationFee);
|
||||||
|
event NewTWAPSlotsMinSet(uint256 newTWAPSlotsMin);
|
||||||
event NewGovernanceProposalCreated(address indexed proposal);
|
event NewGovernanceProposalCreated(address indexed proposal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,11 +41,17 @@ contract InstanceFactoryWithRegistry is InstanceFactory {
|
|||||||
address _governance,
|
address _governance,
|
||||||
address _instanceRegistry,
|
address _instanceRegistry,
|
||||||
address _torn,
|
address _torn,
|
||||||
|
address _UniswapV3Factory,
|
||||||
|
address _WETH,
|
||||||
|
uint16 _TWAPSlotsMin,
|
||||||
uint256 _creationFee
|
uint256 _creationFee
|
||||||
) InstanceFactory(_verifier, _hasher, _merkleTreeHeight, _governance) {
|
) InstanceFactory(_verifier, _hasher, _merkleTreeHeight, _governance) {
|
||||||
governance = _governance;
|
governance = _governance;
|
||||||
instanceRegistry = _instanceRegistry;
|
instanceRegistry = _instanceRegistry;
|
||||||
torn = _torn;
|
torn = _torn;
|
||||||
|
UniswapV3Factory = IUniswapV3Factory(_UniswapV3Factory);
|
||||||
|
WETH = _WETH;
|
||||||
|
TWAPSlotsMin = _TWAPSlotsMin;
|
||||||
creationFee = _creationFee;
|
creationFee = _creationFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,10 +115,22 @@ contract InstanceFactoryWithRegistry is InstanceFactory {
|
|||||||
uint32[] memory _protocolFees
|
uint32[] memory _protocolFees
|
||||||
) internal returns (address) {
|
) internal returns (address) {
|
||||||
require(_token.isContract(), "Token is not contract");
|
require(_token.isContract(), "Token is not contract");
|
||||||
require(_uniswapPoolSwappingFee > 0, "uniswapPoolSwappingFee is zero");
|
|
||||||
require(_denominations.length > 0, "Empty denominations");
|
require(_denominations.length > 0, "Empty denominations");
|
||||||
require(_denominations.length == _protocolFees.length, "Incorrect denominations/fees length");
|
require(_denominations.length == _protocolFees.length, "Incorrect denominations/fees length");
|
||||||
|
|
||||||
|
// check Uniswap Pool
|
||||||
|
for (uint8 i = 0; i < _protocolFees.length; i++) {
|
||||||
|
if (_protocolFees[i] > 0) {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
address proposal = address(
|
address proposal = address(
|
||||||
new AddInstanceProposal(address(this), instanceRegistry, _token, _uniswapPoolSwappingFee, _denominations, _protocolFees)
|
new AddInstanceProposal(address(this), instanceRegistry, _token, _uniswapPoolSwappingFee, _denominations, _protocolFees)
|
||||||
);
|
);
|
||||||
@ -119,4 +143,9 @@ contract InstanceFactoryWithRegistry is InstanceFactory {
|
|||||||
creationFee = _creationFee;
|
creationFee = _creationFee;
|
||||||
emit NewCreationFeeSet(_creationFee);
|
emit NewCreationFeeSet(_creationFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTWAPSlotsMin(uint16 _TWAPSlotsMin) external onlyGovernance {
|
||||||
|
TWAPSlotsMin = _TWAPSlotsMin;
|
||||||
|
emit NewTWAPSlotsMinSet(_TWAPSlotsMin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ async function generate(config = defaultConfig) {
|
|||||||
config.governance,
|
config.governance,
|
||||||
config.instanceRegistry,
|
config.instanceRegistry,
|
||||||
config.TORN,
|
config.TORN,
|
||||||
|
config.UniswapV3Factory,
|
||||||
|
config.WETH,
|
||||||
|
config.TWAPSlotsMin,
|
||||||
config.creationFee,
|
config.creationFee,
|
||||||
])
|
])
|
||||||
.slice(2)
|
.slice(2)
|
||||||
|
@ -101,6 +101,9 @@ describe('Instance Factory With Registry Tests', () => {
|
|||||||
expect(await instanceFactory.implementation()).to.exist
|
expect(await instanceFactory.implementation()).to.exist
|
||||||
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
||||||
expect(await instanceFactory.torn()).to.be.equal(config.TORN)
|
expect(await instanceFactory.torn()).to.be.equal(config.TORN)
|
||||||
|
expect(await instanceFactory.TWAPSlotsMin()).to.be.equal(config.TWAPSlotsMin)
|
||||||
|
expect(await instanceFactory.WETH()).to.be.equal(config.WETH)
|
||||||
|
expect(await instanceFactory.UniswapV3Factory()).to.be.equal(config.UniswapV3Factory)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Governance should be able to set factory params', async function () {
|
it('Governance should be able to set factory params', async function () {
|
||||||
@ -114,20 +117,24 @@ describe('Instance Factory With Registry Tests', () => {
|
|||||||
await instanceFactory.generateNewImplementation(addressZero, addressZero)
|
await instanceFactory.generateNewImplementation(addressZero, addressZero)
|
||||||
await instanceFactory.setMerkleTreeHeight(1)
|
await instanceFactory.setMerkleTreeHeight(1)
|
||||||
await instanceFactory.setCreationFee(0)
|
await instanceFactory.setCreationFee(0)
|
||||||
|
await instanceFactory.setTWAPSlotsMin(0)
|
||||||
|
|
||||||
expect(await instanceFactory.verifier()).to.be.equal(addressZero)
|
expect(await instanceFactory.verifier()).to.be.equal(addressZero)
|
||||||
expect(await instanceFactory.hasher()).to.be.equal(addressZero)
|
expect(await instanceFactory.hasher()).to.be.equal(addressZero)
|
||||||
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(1)
|
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(1)
|
||||||
expect(await instanceFactory.creationFee()).to.be.equal(0)
|
expect(await instanceFactory.creationFee()).to.be.equal(0)
|
||||||
|
expect(await instanceFactory.TWAPSlotsMin()).to.be.equal(0)
|
||||||
|
|
||||||
await instanceFactory.generateNewImplementation(config.verifier, config.hasher)
|
await instanceFactory.generateNewImplementation(config.verifier, config.hasher)
|
||||||
await instanceFactory.setMerkleTreeHeight(config.merkleTreeHeight)
|
await instanceFactory.setMerkleTreeHeight(config.merkleTreeHeight)
|
||||||
await instanceFactory.setCreationFee(config.creationFee)
|
await instanceFactory.setCreationFee(config.creationFee)
|
||||||
|
await instanceFactory.setTWAPSlotsMin(config.TWAPSlotsMin)
|
||||||
|
|
||||||
expect(await instanceFactory.verifier()).to.be.equal(config.verifier)
|
expect(await instanceFactory.verifier()).to.be.equal(config.verifier)
|
||||||
expect(await instanceFactory.hasher()).to.be.equal(config.hasher)
|
expect(await instanceFactory.hasher()).to.be.equal(config.hasher)
|
||||||
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
||||||
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
||||||
|
expect(await instanceFactory.TWAPSlotsMin()).to.be.equal(config.TWAPSlotsMin)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should successfully deploy/propose/execute proposal - add instance', async function () {
|
it('Should successfully deploy/propose/execute proposal - add instance', async function () {
|
||||||
@ -466,4 +473,24 @@ describe('Instance Factory With Registry Tests', () => {
|
|||||||
[BigNumber.from(0).sub(value), value],
|
[BigNumber.from(0).sub(value), value],
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should not deploy proposal with incorrect Uniswap pool', async function () {
|
||||||
|
let { sender, instanceFactory, tornWhale, tornToken } = await loadFixture(fixture)
|
||||||
|
|
||||||
|
// deploy proposal ----------------------------------------------
|
||||||
|
await tornToken.connect(tornWhale).transfer(sender.address, config.creationFee)
|
||||||
|
await tornToken.approve(instanceFactory.address, config.creationFee)
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
instanceFactory
|
||||||
|
.connect(sender)
|
||||||
|
.createProposalApprove(config.COMP, 4000, [ethers.utils.parseEther('100')], [30]),
|
||||||
|
).to.be.revertedWith('Uniswap pool is not exist')
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
instanceFactory
|
||||||
|
.connect(sender)
|
||||||
|
.createProposalApprove(config.COMP, 10000, [ethers.utils.parseEther('100')], [30]),
|
||||||
|
).to.be.revertedWith('Uniswap pool TWAP slots number is low')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user