infrastructure-upgrade/lib/v3-core/test/UniswapV3Factory.spec.ts
T-Hax 735546619e
init
Signed-off-by: T-Hax <>
2023-04-08 18:46:18 +00:00

178 lines
6.9 KiB
TypeScript

import { Wallet } from 'ethers'
import { ethers, waffle } from 'hardhat'
import { UniswapV3Factory } from '../typechain/UniswapV3Factory'
import { expect } from './shared/expect'
import snapshotGasCost from './shared/snapshotGasCost'
import { FeeAmount, getCreate2Address, TICK_SPACINGS } from './shared/utilities'
const { constants } = ethers
const TEST_ADDRESSES: [string, string] = [
'0x1000000000000000000000000000000000000000',
'0x2000000000000000000000000000000000000000',
]
const createFixtureLoader = waffle.createFixtureLoader
describe('UniswapV3Factory', () => {
let wallet: Wallet, other: Wallet
let factory: UniswapV3Factory
let poolBytecode: string
const fixture = async () => {
const factoryFactory = await ethers.getContractFactory('UniswapV3Factory')
return (await factoryFactory.deploy()) as UniswapV3Factory
}
let loadFixture: ReturnType<typeof createFixtureLoader>
before('create fixture loader', async () => {
;[wallet, other] = await (ethers as any).getSigners()
loadFixture = createFixtureLoader([wallet, other])
})
before('load pool bytecode', async () => {
poolBytecode = (await ethers.getContractFactory('UniswapV3Pool')).bytecode
})
beforeEach('deploy factory', async () => {
factory = await loadFixture(fixture)
})
it('owner is deployer', async () => {
expect(await factory.owner()).to.eq(wallet.address)
})
it('factory bytecode size', async () => {
expect(((await waffle.provider.getCode(factory.address)).length - 2) / 2).to.matchSnapshot()
})
it('pool bytecode size', async () => {
await factory.createPool(TEST_ADDRESSES[0], TEST_ADDRESSES[1], FeeAmount.MEDIUM)
const poolAddress = getCreate2Address(factory.address, TEST_ADDRESSES, FeeAmount.MEDIUM, poolBytecode)
expect(((await waffle.provider.getCode(poolAddress)).length - 2) / 2).to.matchSnapshot()
})
it('initial enabled fee amounts', async () => {
expect(await factory.feeAmountTickSpacing(FeeAmount.LOW)).to.eq(TICK_SPACINGS[FeeAmount.LOW])
expect(await factory.feeAmountTickSpacing(FeeAmount.MEDIUM)).to.eq(TICK_SPACINGS[FeeAmount.MEDIUM])
expect(await factory.feeAmountTickSpacing(FeeAmount.HIGH)).to.eq(TICK_SPACINGS[FeeAmount.HIGH])
})
async function createAndCheckPool(
tokens: [string, string],
feeAmount: FeeAmount,
tickSpacing: number = TICK_SPACINGS[feeAmount]
) {
const create2Address = getCreate2Address(factory.address, tokens, feeAmount, poolBytecode)
const create = factory.createPool(tokens[0], tokens[1], feeAmount)
await expect(create)
.to.emit(factory, 'PoolCreated')
.withArgs(TEST_ADDRESSES[0], TEST_ADDRESSES[1], feeAmount, tickSpacing, create2Address)
await expect(factory.createPool(tokens[0], tokens[1], feeAmount)).to.be.reverted
await expect(factory.createPool(tokens[1], tokens[0], feeAmount)).to.be.reverted
expect(await factory.getPool(tokens[0], tokens[1], feeAmount), 'getPool in order').to.eq(create2Address)
expect(await factory.getPool(tokens[1], tokens[0], feeAmount), 'getPool in reverse').to.eq(create2Address)
const poolContractFactory = await ethers.getContractFactory('UniswapV3Pool')
const pool = poolContractFactory.attach(create2Address)
expect(await pool.factory(), 'pool factory address').to.eq(factory.address)
expect(await pool.token0(), 'pool token0').to.eq(TEST_ADDRESSES[0])
expect(await pool.token1(), 'pool token1').to.eq(TEST_ADDRESSES[1])
expect(await pool.fee(), 'pool fee').to.eq(feeAmount)
expect(await pool.tickSpacing(), 'pool tick spacing').to.eq(tickSpacing)
}
describe('#createPool', () => {
it('succeeds for low fee pool', async () => {
await createAndCheckPool(TEST_ADDRESSES, FeeAmount.LOW)
})
it('succeeds for medium fee pool', async () => {
await createAndCheckPool(TEST_ADDRESSES, FeeAmount.MEDIUM)
})
it('succeeds for high fee pool', async () => {
await createAndCheckPool(TEST_ADDRESSES, FeeAmount.HIGH)
})
it('succeeds if tokens are passed in reverse', async () => {
await createAndCheckPool([TEST_ADDRESSES[1], TEST_ADDRESSES[0]], FeeAmount.MEDIUM)
})
it('fails if token a == token b', async () => {
await expect(factory.createPool(TEST_ADDRESSES[0], TEST_ADDRESSES[0], FeeAmount.LOW)).to.be.reverted
})
it('fails if token a is 0 or token b is 0', async () => {
await expect(factory.createPool(TEST_ADDRESSES[0], constants.AddressZero, FeeAmount.LOW)).to.be.reverted
await expect(factory.createPool(constants.AddressZero, TEST_ADDRESSES[0], FeeAmount.LOW)).to.be.reverted
await expect(factory.createPool(constants.AddressZero, constants.AddressZero, FeeAmount.LOW)).to.be.revertedWith(
''
)
})
it('fails if fee amount is not enabled', async () => {
await expect(factory.createPool(TEST_ADDRESSES[0], TEST_ADDRESSES[1], 250)).to.be.reverted
})
it('gas', async () => {
await snapshotGasCost(factory.createPool(TEST_ADDRESSES[0], TEST_ADDRESSES[1], FeeAmount.MEDIUM))
})
})
describe('#setOwner', () => {
it('fails if caller is not owner', async () => {
await expect(factory.connect(other).setOwner(wallet.address)).to.be.reverted
})
it('updates owner', async () => {
await factory.setOwner(other.address)
expect(await factory.owner()).to.eq(other.address)
})
it('emits event', async () => {
await expect(factory.setOwner(other.address))
.to.emit(factory, 'OwnerChanged')
.withArgs(wallet.address, other.address)
})
it('cannot be called by original owner', async () => {
await factory.setOwner(other.address)
await expect(factory.setOwner(wallet.address)).to.be.reverted
})
})
describe('#enableFeeAmount', () => {
it('fails if caller is not owner', async () => {
await expect(factory.connect(other).enableFeeAmount(100, 2)).to.be.reverted
})
it('fails if fee is too great', async () => {
await expect(factory.enableFeeAmount(1000000, 10)).to.be.reverted
})
it('fails if tick spacing is too small', async () => {
await expect(factory.enableFeeAmount(500, 0)).to.be.reverted
})
it('fails if tick spacing is too large', async () => {
await expect(factory.enableFeeAmount(500, 16834)).to.be.reverted
})
it('fails if already initialized', async () => {
await factory.enableFeeAmount(100, 5)
await expect(factory.enableFeeAmount(100, 10)).to.be.reverted
})
it('sets the fee amount in the mapping', async () => {
await factory.enableFeeAmount(100, 5)
expect(await factory.feeAmountTickSpacing(100)).to.eq(5)
})
it('emits an event', async () => {
await expect(factory.enableFeeAmount(100, 5)).to.emit(factory, 'FeeAmountEnabled').withArgs(100, 5)
})
it('enables pool creation', async () => {
await factory.enableFeeAmount(250, 15)
await createAndCheckPool([TEST_ADDRESSES[0], TEST_ADDRESSES[1]], 250, 15)
})
})
})