uni-watcher smoke test (#172)

* Created a smoke test for uni-watcher.

* Added test for createPool.

* Added more pool tests.

* Using ethers instead of hardhat-ethers in smoke test.

Co-authored-by: prathamesh0 <prathamesh.musale0@gmail.com>
This commit is contained in:
Ashwin Phatak 2021-07-30 19:50:56 +05:30 committed by GitHub
parent 18ebed0b36
commit 9a3ac28a5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 739 additions and 13 deletions

View File

@ -34,5 +34,5 @@
deleteOnStart = false
[jobQueue]
dbConnectionString = "postgres://postgres:postgres@localhost/job-queue"
dbConnectionString = "postgres://postgres:postgres@localhost/address-watcher-job-queue"
maxCompletionLag = 300

View File

@ -23,5 +23,14 @@
"allowArgumentsExplicitlyTypedAsAny": true
}
]
}
},
"overrides": [
{
"files": ["*.test.ts", "test/*.ts"],
"rules": {
"no-unused-expressions": "off",
"no-prototype-builtins":"off"
}
}
]
}

View File

@ -3,4 +3,8 @@
node_modules/
build/
tmp/
temp/
temp/
#Hardhat files
cache
artifacts

View File

@ -0,0 +1,6 @@
{
"timeout": "30000",
"bail": true,
"exit": true,
"require": "ts-node/register"
}

View File

@ -86,3 +86,14 @@ To test the watchers locally:
* Send transactions to trigger events
See https://github.com/vulcanize/uniswap-v3-periphery/blob/watcher-ts/demo.md for instructions.
### Smoke test
To run a smoke test:
* Start the server and the job-runner.
* Run:
```bash
$ yarn smoke-test
```

View File

@ -0,0 +1,21 @@
import { HardhatUserConfig } from 'hardhat/config';
import '@nomiclabs/hardhat-waffle';
const config: HardhatUserConfig = {
defaultNetwork: 'localhost',
solidity: {
compilers: [
{
version: '0.7.6'
},
{
version: '0.5.0'
}
]
},
paths: {
sources: './test/contracts'
}
};
export default config;

View File

@ -9,10 +9,12 @@
"server:mock": "MOCK=1 nodemon src/server.ts -f environments/local.toml",
"job-runner": "DEBUG=vulcanize:* nodemon src/job-runner.ts -f environments/local.toml",
"fill": "DEBUG=vulcanize:* ts-node src/fill.ts -f environments/local.toml",
"test": "mocha -r ts-node/register src/**/*.spec.ts",
"test": "mocha src/**/*.spec.ts",
"lint": "eslint .",
"build": "tsc",
"watch:contract": "ts-node src/cli/watch-contract.ts --configFile environments/local.toml"
"watch:contract": "ts-node src/cli/watch-contract.ts --configFile environments/local.toml",
"test:compile": "hardhat compile",
"smoke-test": "yarn test:compile && mocha src/smoke.test.ts"
},
"repository": {
"type": "git",
@ -52,12 +54,18 @@
},
"devDependencies": {
"@ethersproject/abi": "^5.3.0",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@types/chai": "^4.2.18",
"@types/express": "^4.17.11",
"@types/fs-extra": "^9.0.11",
"@types/json-bigint": "^1.0.0",
"@types/mocha": "^8.2.2",
"@types/yargs": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.1.1",
"chai": "^4.3.4",
"eslint": "^7.27.0",
"eslint-config-semistandard": "^15.0.1",
@ -66,7 +74,10 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"hardhat": "^2.3.0",
"mocha": "^8.4.0",
"nodemon": "^2.0.7"
"nodemon": "^2.0.7",
"ts-node": "^10.0.0",
"typescript": "^4.3.2"
}
}

View File

@ -1,10 +1,11 @@
import assert from 'assert';
import yargs from 'yargs';
import 'reflect-metadata';
import { ethers } from 'ethers';
import { Config, getConfig } from '@vulcanize/util';
import { Database } from '../database';
import { watchContract } from '../utils/index';
(async () => {
const argv = await yargs.parserConfiguration({
@ -43,9 +44,7 @@ import { Database } from '../database';
const db = new Database(dbConfig);
await db.init();
// Always use the checksum address (https://docs.ethers.io/v5/api/utils/address/#utils-getAddress).
const address = ethers.utils.getAddress(argv.address);
await watchContract(db, argv.address, argv.kind, argv.startingBlock);
await db.saveContract(address, argv.kind, argv.startingBlock);
await db.close();
})();

View File

@ -0,0 +1,268 @@
import { expect, assert } from 'chai';
import { ethers, Contract, Signer } from 'ethers';
import 'reflect-metadata';
import 'mocha';
import { Config, getConfig } from '@vulcanize/util';
import { Client as UniClient } from '@vulcanize/uni-watcher';
import { getCache } from '@vulcanize/cache';
import { EthClient } from '@vulcanize/ipld-eth-client';
import {
abi as FACTORY_ABI,
bytecode as FACTORY_BYTECODE
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json';
import {
abi as POOL_ABI
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json';
import { Indexer } from './indexer';
import { Database } from './database';
import { watchContract } from './utils/index';
import { testCreatePool, testInitialize } from '../test/utils';
import {
abi as TESTERC20_ABI,
bytecode as TESTERC20_BYTECODE
} from '../artifacts/test/contracts/TestERC20.sol/TestERC20.json';
import {
abi as TESTUNISWAPV3CALLEE_ABI,
bytecode as TESTUNISWAPV3CALLEE_BYTECODE
} from '../artifacts/test/contracts/TestUniswapV3Callee.sol/TestUniswapV3Callee.json';
const TICK_MIN = -887272;
const TICK_MAX = 887272;
const getMinTick = (tickSpacing: number) => Math.ceil(TICK_MIN / tickSpacing) * tickSpacing;
const getMaxTick = (tickSpacing: number) => Math.floor(TICK_MAX / tickSpacing) * tickSpacing;
describe('uni-watcher', () => {
let factory: Contract;
let token0: Contract;
let token1: Contract;
let pool: Contract;
let poolAddress: string;
let tickLower: number;
let tickUpper: number;
let config: Config;
let db: Database;
let uniClient: UniClient;
let ethClient: EthClient;
let signer: Signer;
let recipient: string;
before(async () => {
const configFile = './environments/local.toml';
config = await getConfig(configFile);
const { database: dbConfig, upstream, server: { host, port } } = config;
assert(dbConfig, 'Missing dbConfig.');
assert(upstream, 'Missing upstream.');
assert(host, 'Missing host.');
assert(port, 'Missing port.');
const { ethServer: { gqlApiEndpoint, gqlPostgraphileEndpoint }, cache: cacheConfig } = upstream;
assert(gqlApiEndpoint, 'Missing upstream ethServer.gqlApiEndpoint.');
assert(gqlPostgraphileEndpoint, 'Missing upstream ethServer.gqlPostgraphileEndpoint.');
assert(cacheConfig, 'Missing dbConfig.');
db = new Database(dbConfig);
await db.init();
const cache = await getCache(cacheConfig);
ethClient = new EthClient({
gqlEndpoint: gqlApiEndpoint,
gqlSubscriptionEndpoint: gqlPostgraphileEndpoint,
cache
});
const endpoint = `http://${host}:${port}/graphql`;
const gqlEndpoint = endpoint;
const gqlSubscriptionEndpoint = endpoint;
uniClient = new UniClient({
gqlEndpoint,
gqlSubscriptionEndpoint
});
const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
signer = provider.getSigner();
recipient = await signer.getAddress();
});
after(async () => {
await db.close();
});
it('should deploy contract factory', async () => {
// Deploy factory from uniswap package.
const Factory = new ethers.ContractFactory(FACTORY_ABI, FACTORY_BYTECODE, signer);
factory = await Factory.deploy();
expect(factory.address).to.not.be.empty;
});
it('should watch factory contract', async () => {
// Watch factory contract.
await watchContract(db, factory.address, 'factory', 100);
// Verifying with the db.
const indexer = new Indexer(config, db, ethClient);
assert(await indexer.isUniswapContract(factory.address), 'Factory contract not added to database.');
});
it('should deploy 2 tokens', async () => {
// Deploy 2 tokens.
const Token = new ethers.ContractFactory(TESTERC20_ABI, TESTERC20_BYTECODE, signer);
token0 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
expect(token0.address).to.not.be.empty;
token1 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
expect(token1.address).to.not.be.empty;
});
it('should create pool', async () => {
const fee = 500;
pool = await testCreatePool(uniClient, factory, token0, token1, POOL_ABI, signer, fee);
poolAddress = pool.address;
});
it('should initialize pool', async () => {
const sqrtPrice = '4295128939';
await testInitialize(uniClient, pool, TICK_MIN, sqrtPrice);
});
it('should mint specified amount', done => {
(async () => {
const amount = '10';
const approveAmount = BigInt(1000000000000000000000000);
const TestUniswapV3Callee = new ethers.ContractFactory(TESTUNISWAPV3CALLEE_ABI, TESTUNISWAPV3CALLEE_BYTECODE, signer);
const poolCallee = await TestUniswapV3Callee.deploy();
const tickSpacing = await pool.tickSpacing();
// https://github.com/Uniswap/uniswap-v3-core/blob/main/test/UniswapV3Pool.spec.ts#L196
tickLower = getMinTick(tickSpacing);
tickUpper = getMaxTick(tickSpacing);
// Approving tokens for TestUniswapV3Callee contract.
// https://github.com/Uniswap/uniswap-v3-core/blob/main/test/shared/utilities.ts#L187
const t0 = await token0.approve(poolCallee.address, approveAmount);
await t0.wait();
const t1 = await token1.approve(poolCallee.address, approveAmount);
await t1.wait();
// Subscribe using UniClient.
const subscription = await uniClient.watchEvents((value: any) => {
if (value.event.__typename === 'MintEvent') {
expect(value.block).to.not.be.empty;
expect(value.tx).to.not.be.empty;
expect(value.contract).to.equal(pool.address);
expect(value.eventIndex).to.be.a('number');
expect(value.event.__typename).to.equal('MintEvent');
expect(value.event.sender).to.equal(poolCallee.address);
expect(value.event.owner).to.equal(recipient);
expect(value.event.tickLower).to.equal(tickLower.toString());
expect(value.event.tickUpper).to.equal(tickUpper.toString());
expect(value.event.amount).to.equal(amount);
expect(value.event.amount0).to.not.be.empty;
expect(value.event.amount1).to.not.be.empty;
expect(value.proof).to.not.be.empty;
if (subscription) {
subscription.unsubscribe();
}
done();
}
});
// Pool mint.
await poolCallee.mint(pool.address, recipient, BigInt(tickLower), BigInt(tickUpper), BigInt(amount));
})().catch((error) => {
console.error(error);
});
});
it('should burn specified amount', done => {
(async () => {
const amount = '10';
const tickSpacing = await pool.tickSpacing();
// https://github.com/Uniswap/uniswap-v3-core/blob/main/test/UniswapV3Pool.spec.ts#L196
const tickLower = getMinTick(tickSpacing);
const tickUpper = getMaxTick(tickSpacing);
// Subscribe using UniClient.
const subscription = await uniClient.watchEvents((value: any) => {
if (value.event.__typename === 'BurnEvent') {
expect(value.block).to.not.be.empty;
expect(value.tx).to.not.be.empty;
expect(value.contract).to.equal(pool.address);
expect(value.eventIndex).to.be.a('number');
expect(value.event.__typename).to.equal('BurnEvent');
expect(value.event.owner).to.equal(recipient);
expect(value.event.tickLower).to.equal(tickLower.toString());
expect(value.event.tickUpper).to.equal(tickUpper.toString());
expect(value.event.amount).to.equal(amount);
expect(value.event.amount0).to.not.be.empty;
expect(value.event.amount1).to.not.be.empty;
expect(value.proof).to.not.be.empty;
if (subscription) {
subscription.unsubscribe();
}
done();
}
});
// Pool burn.
await pool.burn(BigInt(tickLower), BigInt(tickUpper), BigInt(amount));
})().catch((error) => {
console.error(error);
});
});
it('should swap pool tokens', done => {
(async () => {
const sqrtPrice = '4295128938';
const TestUniswapV3Callee = new ethers.ContractFactory(TESTUNISWAPV3CALLEE_ABI, TESTUNISWAPV3CALLEE_BYTECODE, signer);
const poolCallee = await TestUniswapV3Callee.deploy();
// Subscribe using UniClient.
const subscription = await uniClient.watchEvents((value: any) => {
if (value.event.__typename === 'SwapEvent') {
expect(value.block).to.not.be.empty;
expect(value.tx).to.not.be.empty;
expect(value.contract).to.equal(poolAddress);
expect(value.eventIndex).to.be.a('number');
expect(value.event.__typename).to.equal('SwapEvent');
expect(value.event.sender).to.equal(poolCallee.address);
expect(value.event.recipient).to.equal(recipient);
expect(value.event.amount0).to.not.be.empty;
expect(value.event.amount1).to.not.be.empty;
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
expect(value.event.liquidity).to.not.be.empty;
expect(value.event.tick).to.equal(TICK_MIN.toString());
expect(value.proof).to.not.be.empty;
if (subscription) {
subscription.unsubscribe();
}
done();
}
});
await poolCallee.swapToLowerSqrtPrice(poolAddress, BigInt(sqrtPrice), recipient);
})().catch((error) => {
console.error(error);
});
});
});

View File

@ -0,0 +1,10 @@
import { ethers } from 'ethers';
import { Database } from '../database';
export async function watchContract (db: Database, address: string, kind: string, startingBlock: number): Promise<void> {
// Always use the checksum address (https://docs.ethers.io/v5/api/utils/address/#utils-getAddress).
const contractAddress = ethers.utils.getAddress(address);
await db.saveContract(contractAddress, kind, startingBlock);
}

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.7.6;
import '@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol';
contract TestERC20 is IERC20Minimal {
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;
constructor(uint256 amountToMint) {
mint(msg.sender, amountToMint);
}
function mint(address to, uint256 amount) public {
uint256 balanceNext = balanceOf[to] + amount;
require(balanceNext >= amount, 'overflow balance');
balanceOf[to] = balanceNext;
}
function transfer(address recipient, uint256 amount) external override returns (bool) {
uint256 balanceBefore = balanceOf[msg.sender];
require(balanceBefore >= amount, 'insufficient balance');
balanceOf[msg.sender] = balanceBefore - amount;
uint256 balanceRecipient = balanceOf[recipient];
require(balanceRecipient + amount >= balanceRecipient, 'recipient balance overflow');
balanceOf[recipient] = balanceRecipient + amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) external override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) external override returns (bool) {
uint256 allowanceBefore = allowance[sender][msg.sender];
require(allowanceBefore >= amount, 'allowance insufficient');
allowance[sender][msg.sender] = allowanceBefore - amount;
uint256 balanceRecipient = balanceOf[recipient];
require(balanceRecipient + amount >= balanceRecipient, 'overflow balance recipient');
balanceOf[recipient] = balanceRecipient + amount;
uint256 balanceSender = balanceOf[sender];
require(balanceSender >= amount, 'underflow balance sender');
balanceOf[sender] = balanceSender - amount;
emit Transfer(sender, recipient, amount);
return true;
}
}

View File

@ -0,0 +1,142 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.7.6;
import '@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol';
import '@uniswap/v3-core/contracts/libraries/SafeCast.sol';
import '@uniswap/v3-core/contracts/libraries/TickMath.sol';
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol';
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
contract TestUniswapV3Callee is IUniswapV3MintCallback, IUniswapV3SwapCallback, IUniswapV3FlashCallback {
using SafeCast for uint256;
function swapExact0For1(
address pool,
uint256 amount0In,
address recipient,
uint160 sqrtPriceLimitX96
) external {
IUniswapV3Pool(pool).swap(recipient, true, amount0In.toInt256(), sqrtPriceLimitX96, abi.encode(msg.sender));
}
function swap0ForExact1(
address pool,
uint256 amount1Out,
address recipient,
uint160 sqrtPriceLimitX96
) external {
IUniswapV3Pool(pool).swap(recipient, true, -amount1Out.toInt256(), sqrtPriceLimitX96, abi.encode(msg.sender));
}
function swapExact1For0(
address pool,
uint256 amount1In,
address recipient,
uint160 sqrtPriceLimitX96
) external {
IUniswapV3Pool(pool).swap(recipient, false, amount1In.toInt256(), sqrtPriceLimitX96, abi.encode(msg.sender));
}
function swap1ForExact0(
address pool,
uint256 amount0Out,
address recipient,
uint160 sqrtPriceLimitX96
) external {
IUniswapV3Pool(pool).swap(recipient, false, -amount0Out.toInt256(), sqrtPriceLimitX96, abi.encode(msg.sender));
}
function swapToLowerSqrtPrice(
address pool,
uint160 sqrtPriceX96,
address recipient
) external {
IUniswapV3Pool(pool).swap(recipient, true, type(int256).max, sqrtPriceX96, abi.encode(msg.sender));
}
function swapToHigherSqrtPrice(
address pool,
uint160 sqrtPriceX96,
address recipient
) external {
IUniswapV3Pool(pool).swap(recipient, false, type(int256).max, sqrtPriceX96, abi.encode(msg.sender));
}
event SwapCallback(int256 amount0Delta, int256 amount1Delta);
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external override {
address sender = abi.decode(data, (address));
emit SwapCallback(amount0Delta, amount1Delta);
if (amount0Delta > 0) {
IERC20Minimal(IUniswapV3Pool(msg.sender).token0()).transferFrom(sender, msg.sender, uint256(amount0Delta));
} else if (amount1Delta > 0) {
IERC20Minimal(IUniswapV3Pool(msg.sender).token1()).transferFrom(sender, msg.sender, uint256(amount1Delta));
} else {
// if both are not gt 0, both must be 0.
assert(amount0Delta == 0 && amount1Delta == 0);
}
}
function mint(
address pool,
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount
) external {
IUniswapV3Pool(pool).mint(recipient, tickLower, tickUpper, amount, abi.encode(msg.sender));
}
event MintCallback(uint256 amount0Owed, uint256 amount1Owed);
function uniswapV3MintCallback(
uint256 amount0Owed,
uint256 amount1Owed,
bytes calldata data
) external override {
address sender = abi.decode(data, (address));
emit MintCallback(amount0Owed, amount1Owed);
if (amount0Owed > 0)
IERC20Minimal(IUniswapV3Pool(msg.sender).token0()).transferFrom(sender, msg.sender, amount0Owed);
if (amount1Owed > 0)
IERC20Minimal(IUniswapV3Pool(msg.sender).token1()).transferFrom(sender, msg.sender, amount1Owed);
}
event FlashCallback(uint256 fee0, uint256 fee1);
function flash(
address pool,
address recipient,
uint256 amount0,
uint256 amount1,
uint256 pay0,
uint256 pay1
) external {
IUniswapV3Pool(pool).flash(recipient, amount0, amount1, abi.encode(msg.sender, pay0, pay1));
}
function uniswapV3FlashCallback(
uint256 fee0,
uint256 fee1,
bytes calldata data
) external override {
emit FlashCallback(fee0, fee1);
(address sender, uint256 pay0, uint256 pay1) = abi.decode(data, (address, uint256, uint256));
if (pay0 > 0) IERC20Minimal(IUniswapV3Pool(msg.sender).token0()).transferFrom(sender, msg.sender, pay0);
if (pay1 > 0) IERC20Minimal(IUniswapV3Pool(msg.sender).token1()).transferFrom(sender, msg.sender, pay1);
}
}

View File

@ -0,0 +1,119 @@
import { ethers, utils, Contract, Signer, BigNumber } from 'ethers';
import { expect } from 'chai';
import 'mocha';
import { Client as UniClient } from '@vulcanize/uni-watcher';
// https://github.com/ethers-io/ethers.js/issues/195
export function linkLibraries (
{
bytecode,
linkReferences
}: {
bytecode: string
linkReferences: { [fileName: string]: { [contractName: string]: { length: number; start: number }[] } }
},
libraries: { [libraryName: string]: string }): string {
Object.keys(linkReferences).forEach((fileName) => {
Object.keys(linkReferences[fileName]).forEach((contractName) => {
if (!libraries.hasOwnProperty(contractName)) {
throw new Error(`Missing link library name ${contractName}`);
}
const address = utils.getAddress(libraries[contractName]).toLowerCase().slice(2);
linkReferences[fileName][contractName].forEach(({ start: byteStart, length: byteLength }) => {
const start = 2 + byteStart * 2;
const length = byteLength * 2;
bytecode = bytecode
.slice(0, start)
.concat(address)
.concat(bytecode.slice(start + length, bytecode.length));
});
});
});
return bytecode;
}
export async function testCreatePool (
uniClient: UniClient,
factory: Contract,
token0: Contract,
token1: Contract,
poolAbi: any,
signer: Signer,
fee: number): Promise<Contract> {
return new Promise((resolve, reject) => {
(async () => {
try {
const subscription = await uniClient.watchEvents((value: any) => {
// Function gets called with previous events. Check for PoolCreatedEvent.
if (value.event.__typename === 'PoolCreatedEvent') {
expect(value.block).to.not.be.empty;
expect(value.tx).to.not.be.empty;
expect(value.contract).to.equal(factory.address);
expect(value.eventIndex).to.be.a('number');
expect(value.event.__typename).to.equal('PoolCreatedEvent');
const tokens = new Set([token0.address, token1.address]);
expect(new Set([value.event.token0, value.event.token1])).to.eql(tokens);
expect(value.event.fee).to.equal(fee.toString());
expect(value.event.tickSpacing).to.not.be.empty;
expect(value.event.pool).to.not.be.empty;
expect(value.proof).to.not.be.empty;
const poolAddress = value.event.pool;
const pool = new ethers.Contract(poolAddress, poolAbi, signer);
if (subscription) {
subscription.unsubscribe();
}
resolve(pool);
}
});
// Create pool.
await factory.createPool(token0.address, token1.address, fee);
} catch (error) {
reject(error);
}
})();
});
}
export function testInitialize (
uniClient: UniClient,
pool: Contract,
expectedTick: number,
sqrtPrice: string): Promise<void> {
return new Promise((resolve, reject) => {
try {
(async () => {
// Subscribe using UniClient.
const subscription = await uniClient.watchEvents((value: any) => {
// Function gets called with previous events. Check for InitializeEvent.
if (value.event.__typename === 'InitializeEvent') {
expect(value.block).to.not.be.empty;
expect(value.tx).to.not.be.empty;
expect(value.contract).to.equal(pool.address);
expect(value.eventIndex).to.be.a('number');
expect(value.event.__typename).to.equal('InitializeEvent');
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
expect(value.event.tick).to.equal(expectedTick.toString());
expect(value.proof).to.not.be.empty;
if (subscription) {
subscription.unsubscribe();
}
resolve();
}
});
// Pool initialize.
await pool.initialize(BigNumber.from(sqrtPrice));
})();
} catch (error) {
reject(error);
}
});
}

View File

@ -1890,6 +1890,11 @@
dependencies:
"@octokit/openapi-types" "^7.2.3"
"@openzeppelin/contracts@3.4.1-solc-0.7-2":
version "3.4.1-solc-0.7-2"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92"
integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q==
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@ -2576,6 +2581,33 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@uniswap/lib@^4.0.1-alpha":
version "4.0.1-alpha"
resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02"
integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA==
"@uniswap/v2-core@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425"
integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q==
"@uniswap/v3-core@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d"
integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA==
"@uniswap/v3-periphery@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.1.1.tgz#be6dfca7b29318ea0d76a7baf15d3b33c3c5e90a"
integrity sha512-orqD2Xy4lxVPF6pxd7ECSJY0gzEuqyeVSDHjzM86uWxOXlA4Nlh5pvI959KaS32pSOFBOVVA4XbbZywbJj+CZg==
dependencies:
"@openzeppelin/contracts" "3.4.1-solc-0.7-2"
"@uniswap/lib" "^4.0.1-alpha"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
base64-sol "1.0.1"
hardhat-watcher "^2.1.1"
"@wry/context@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.6.0.tgz#f903eceb89d238ef7e8168ed30f4511f92d83e06"
@ -2840,7 +2872,7 @@ any-promise@^1.0.0:
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
anymatch@~3.1.1:
anymatch@~3.1.1, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@ -3785,6 +3817,11 @@ base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
base64-sol@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6"
integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg==
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@ -4358,6 +4395,21 @@ chokidar@3.5.1, chokidar@^3.2.2, chokidar@^3.4.0:
optionalDependencies:
fsevents "~2.3.1"
chokidar@^3.4.3:
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
chownr@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
@ -6755,7 +6807,7 @@ fsevents@~2.1.1:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
fsevents@~2.3.1:
fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -6961,7 +7013,7 @@ gitconfiglocal@^1.0.0:
dependencies:
ini "^1.3.2"
glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0:
glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@ -7204,6 +7256,13 @@ hard-rejection@^2.1.0:
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
hardhat-watcher@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.1.1.tgz#8b05fec429ed45da11808bbf6054a90f3e34c51a"
integrity sha512-zilmvxAYD34IofBrwOliQn4z92UiDmt2c949DW4Gokf0vS0qk4YTfVCi/LmUBICThGygNANE3WfnRTpjCJGtDA==
dependencies:
chokidar "^3.4.3"
hardhat@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.3.0.tgz#5c29f8b4d08155c3dc8c908af9713fd5079522d5"
@ -11131,6 +11190,13 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
rechoir@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"