npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@revxchain/uniswap-v3-utils

v1.2.2

Published

Solidity library with various utility functions for UniswapV3 interactions

Readme

UniswapV3 Utils

A Solidity library with various utility functions for UniswapV3 interactions — spot price quotes, TWAP quotes, calculation of amounts for providing liquidity and existing position, sqrtPriceX96 calculations, valid tick and accumulated fee getters.

Ethereum Solidity Uniswap V3 Hardhat License: MIT GitHub Actions Workflow Status NPM Version


Table of Contents


Overview

UniswapV3Utils is a Solidity library that contains the common math operations and getters needed when integrating with the UniswapV3 protocol. It consolidates spot price quotes, TWAP quotes, calculation of amounts for providing liquidity and existing position, sqrtPriceX96 calculations, valid tick and accumulated fee getters into a single module.

It also includes a Hardhat Fixture for full local deployment of the UniswapV3 protocol and a setup for testing integration using a mainnet fork.


Main Features

| Feature | Function | |---|---| | TWAP quote (default 15 min window) | getTimeWeightedAmountOut(pool, tokenIn, amountIn) | | TWAP quote with spot-price fallback | getForceTimeWeightedAmountOut(pool, tokenIn, amountIn) | | Full TWAP quote with custom window and force flag | getTimeWeightedAmountOut(pool, tokenIn, amountIn, secondsAgo, force) | | Spot price quote | getAmountOut(pool, tokenIn, amountIn) | | Upper sqrtPriceX96 boundary for a position | getUpperSqrtPriceX96(lowerSqrtPriceX96, currentSqrtPriceX96, amount0, amount1) | | Lower sqrtPriceX96 boundary for a position | getLowerSqrtPriceX96(currentSqrtPriceX96, upperSqrtPriceX96, amount0, amount1) | | Proportional token amounts for a position | getProportionalAmounts(pool, amount0, amount1, tickLower, tickUpper) | | Nearest valid tick from sqrtPriceX96 | getValidTick(sqrtPriceX96, tickSpacing) | | Nearest valid tick from tick | getValidTick(tick, tickSpacing) | | sqrtPriceX96 from token amount ratio | getSqrtPriceX96(amount0, amount1) | | Accumulated position fees | getAccumulatedFees(positionManager, pool, tokenId) | | Principal token amounts in the existed position | getPositionLiquidity(positionManager, pool, tokenId) |


Project Structure

uniswap-v3-utils/
├── src/
│   ├── UniswapV3Utils.sol                       # Main Solidity library
│   │
│   ├── interfaces/
│   │   ├── IUniswapV3PoolTyped.sol              # Struct-typed pool interface
│   │   └── INonfungiblePositionManagerTyped.sol # Struct-typed position manager interface
│   │
│   ├── libraries/
│   │   ├── uniswap-v3-periphery-0.8/            # LiquidityAmounts, OracleLibrary
│   │   └── sir-trading-core/                    # FullMath
│   │
│   └── mocks/
│       ├── ERC20Token.sol                       # Test ERC20 token
│       ├── Multicall2.sol                       # Mock Multicall2
│       └── Permit2.sol                          # Mock Permit2
│
├── test/
│   ├── UniswapV3DeploymentFixture.js            # Full UniswapV3 local deployment + mainnet fork setup
│   ├── UniswapV3UtilsFixture.js                 # Fixture for library test
│   ├── UniswapV3Utils.js                        # Main test suite
│   ├── FixturesTest.js                          # Fixture tests
│   └── Utils.js                                 # Test helpers
│
├── artifacts/                                   # Compiled contract artifacts
├── coverage/                                    # Code coverage reports
├── build/                                       # Pre-compiled artifacts (uniswap, weth, multicall2)
├── lib/                                         # Submodule dev dependencies
├── env.example                                  # Example of .env file
├── uniswap.addresses.json                       # Uniswap deployments per chain
├── hardhat.config.js                            # Hardhat configuration
├── solc.compilers.json                          # Per-contract compiler overrides
├── slither.config.json                          # Slither analyzer config for CI
├── package.json                                 # Dependencies and package info
└── README.md                                    # This file

Key Components

UniswapV3Utils.sol

The primary Solidity library. Relies on the following math libraries:

UniswapV3DeploymentFixture()

Hardhat fixture that deploys the complete UniswapV3 protocol from pre-compiled artifacts stored in build/:

| Contract | Source | |---|---| | WETH9 | build/gnosis/canonical-weth/ | | UniswapV3Factory | build/@uniswap/v3-core-0.7/ | | NFTDescriptor | build/@uniswap/v3-periphery-0.7/ | | NonfungibleTokenPositionDescriptor | build/@uniswap/v3-periphery-0.7/ | | NonfungiblePositionManager | build/@uniswap/v3-periphery-0.7/ | | SwapRouter01 | build/@uniswap/v3-periphery-0.7/ | | SwapRouter02 | build/@uniswap/swap-router-contracts/ | | QuoterV1 | build/@uniswap/v3-periphery-0.7/ | | QuoterV2 | build/@uniswap/v3-periphery-0.7/ | | TickLens | build/@uniswap/v3-periphery-0.7/ | | UniswapInterfaceMulticall | build/@uniswap/v3-periphery-0.7/ | | Multicall2 | build/sky-ecosystem/multicall/ | | Permit2 | build/@uniswap/permit2/ | | UniversalRouter | build/@uniswap/universal-router/ |

createUniswapV3DeploymentFixtureCustomWETH()

Hardhat fixture creation function that deploys the complete UniswapV3 protocol from pre-compiled artifacts stored in build/ with custom WETH contract.

UniswapV3MainnetForkSetup()

The function uses uniswap.addresses.json to attach to live deployments for mainnet fork testing.

V3 Supported networks

| Network | Chain ID | |---|---| | Ethereum | 1 | | Unichain | 130 | | Arbitrum | 42161 | | Optimism | 10 | | Polygon | 137 | | Base | 8453 | | BSC | 56 | | Avalanche | 43114 | | Celo | 42220 | | Blast | 81457 | | Zora | 7777777 | | Monad | 143 | | MegaETH | 4326 | | WorldChain | 480 |

[!WARNING] For networks where Ether is not the native asset, the WETH contract is used regardless. In reality, depends on the network; this is the wrapped version of the native asset.

[!WARNING] Each network has a unique set of deployed contracts. For example, some networks might lack SwapRouter01 or one of the Multicall contracts. Must familiarize with the deployments of the selected network before using it. For unsupported networks or/and contracts, zero-address placeholders will be used.


Dependencies

Required dependencies

[!NOTE] Required to import UniswapV3Utils library.

| Package | Version | Description | |---|---|---| | @uniswap/v3-core | 1.0.2-solc-0.8-simulate | UniswapV3 core contracts | | solmate | ^6.5.0 | FixedPointMathLib for sqrt function |

Optional dev dependencies

[!NOTE] Required to import pre-made Uniswap fixtures and setups.

| Package | Tag | Version | Description | |---|---|---|---| | hardhat | hh2 | ^2.28.6 | Hardhat development environment | | @nomicfoundation/hardhat-toolbox | hh2 | ^6.1.0 | Hardhat development toolkit (helpers, ethers, chai, coverage etc.) |


Installation

Repository

Step 1: Clone the repository

git clone https://github.com/RevxChain/uniswap-v3-utils.git
cd uniswap-v3-utils

Step 2: Install dependencies

npm install
git submodule update --init --recursive

Step 3: Create environment file (optional)

cp .env.example .env

Edit .env with your configuration:

# PRIVATE KEYS
PRIVATE_KEY = your_private_key_here

# MAINNET FORK TEST
FORK_RPC_URL = https://eth.llamarpc.com
FORK_BLOCK_NUMBER = 24540000

# RPC URLS
ETH_RPC_URL = https://eth.llamarpc.com

Step 4: Compile contracts

npx hardhat compile

Compiles all Solidity contracts and generates artifacts.

Step 5: Run tests

npx hardhat test

Step 6: Run coverage

npx hardhat coverage

Step 7: Run tests with custom fuzzing runs

Set fuzzing runs value in the hardhat.config.js:

fuzzing: {
    enabled: true,
    runs: 100
},

Run tests:

npx hardhat test

Run coverage:

npx hardhat coverage

Package

npm install @revxchain/uniswap-v3-utils

Quick Start

Solidity library:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {UniswapV3Utils} from "@revxchain/uniswap-v3-utils/src/UniswapV3Utils.sol";

contract MyContract {

    /// @notice Calculates the output amount for a token swap using the default TWAP observation 
    /// window (15 minutes).
    function getTimeWeightedAmountOut(
        address pool, 
        address tokenIn, 
        uint256 amountIn
    ) external view returns(uint256 amountOut) {
        return UniswapV3Utils.getTimeWeightedAmountOut(pool, tokenIn, amountIn);
    }

    /// @notice Calculates the output amount using TWAP with fallback to spot price if observation 
    /// data unavailable.
    function getForceTimeWeightedAmountOut(
        address pool, 
        address tokenIn, 
        uint256 amountIn
    ) external view returns(uint256 amountOut) {
        return UniswapV3Utils.getForceTimeWeightedAmountOut(pool, tokenIn, amountIn);
    }

    /// @notice Calculates the output amount for a token swap using a custom TWAP observation window 
    /// with optional force fallback.
    function getTimeWeightedAmountOut(
        address pool, 
        address tokenIn, 
        uint256 amountIn, 
        uint32 secondsAgo,
        bool force
    ) external view returns(uint256 amountOut) {
        return UniswapV3Utils.getTimeWeightedAmountOut(pool, tokenIn, amountIn, secondsAgo, force);
    }

    /// @notice Calculates the output amount for a token swap at the current spot price.
    function getAmountOut(
        address pool, 
        address tokenIn, 
        uint256 amountIn
    ) external view returns(uint256 amountOut) {
        return UniswapV3Utils.getAmountOut(pool, tokenIn, amountIn);
    }

    /// @notice Calculates the upper price boundary (sqrtPriceX96) for a liquidity position.
    function getUpperSqrtPriceX96(
        uint160 lowerSqrtPriceX96, 
        uint160 currentSqrtPriceX96,
        uint256 amount0,
        uint256 amount1
    ) external pure returns(uint160 upperSqrtPriceX96) {
        return UniswapV3Utils.getUpperSqrtPriceX96(
            lowerSqrtPriceX96, 
            currentSqrtPriceX96,
            amount0,
            amount1
        );
    }

    /// @notice Calculates the lower price boundary (sqrtPriceX96) for a liquidity position.
    function getLowerSqrtPriceX96(
        uint160 currentSqrtPriceX96,
        uint160 upperSqrtPriceX96,
        uint256 amount0,
        uint256 amount1
    ) external pure returns(uint256 lowerSqrtPriceX96) {
        return UniswapV3Utils.getLowerSqrtPriceX96(
            currentSqrtPriceX96,
            upperSqrtPriceX96,
            amount0,
            amount1
        );
    }

    /// @notice Calculates the proportional amounts of both tokens required to provide liquidity
    /// within a specified price range.
    function getProportionalAmounts(
        address pool,
        uint256 amount0,
        uint256 amount1,
        int24 tickLower,
        int24 tickUpper
    ) external view returns(uint256 amount0Required, uint256 amount1Required) {
        return UniswapV3Utils.getProportionalAmounts(
            pool,
            amount0,
            amount1,
            tickLower,
            tickUpper
        );
    }

    /// @notice Finds the nearest valid tick for a specified square root price, aligned 
    /// to the specified tick spacing.
    function getValidTick(
        uint160 sqrtPriceX96, 
        int24 tickSpacing
    ) external pure returns(int24 validTick) {
        return UniswapV3Utils.getValidTick(sqrtPriceX96, tickSpacing);
    }

    /// @notice Finds the nearest valid tick for a specified tick, aligned to the 
    /// specified tick spacing.
    function getValidTick(
        int24 tick, 
        int24 tickSpacing
    ) external pure returns(int24 validTick) {
        return UniswapV3Utils.getValidTick(tick, tickSpacing);
    }

    /// @notice Calculates the effective square root of price (in Q64.96 format) from the ratio 
    /// of two token amounts.
    function getSqrtPriceX96(
        uint256 amount0, 
        uint256 amount1
    ) external pure returns(uint160 sqrtPriceX96) {
        return UniswapV3Utils.getSqrtPriceX96(amount0, amount1);
    }

    /// @notice Calculates the accumulated trading fees for a UniswapV3 liquidity position.
    function getAccumulatedFees(
        address positionManager, 
        address pool, 
        uint256 tokenId
    ) external view returns(uint256 amount0, uint256 amount1) {
        return UniswapV3Utils.getAccumulatedFees(positionManager, pool, tokenId);
    }

    /// @notice Calculates the principal token amounts (amount0 and amount1) represented 
    /// by a position's liquidity.
    function getPositionLiquidity(
        address positionManager, 
        address pool, 
        uint256 tokenId
    ) external view returns(uint256 amount0, uint256 amount1) {
        return UniswapV3Utils.getPositionLiquidity(positionManager, pool, tokenId);
    }
}

Hardhat test environment:

UniswapV3DeploymentFixture()

const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");
const { UniswapV3DeploymentFixture } = require("@revxchain/uniswap-v3-utils/test/UniswapV3DeploymentFixture.js");

const {
    uniswapV3Deployer, weth, uniswapFactory, descriptorLibrary, tokenDescriptor, nonfungiblePositionManager, 
    swapRouter01, swapRouter02, quoter01, quoter02, tickLens, multicall, multicall2, permit2, 
    universalRouter, uniswapV3PoolBytecode, uniswapV3PoolAbi
} = await loadFixture(UniswapV3DeploymentFixture);

createUniswapV3DeploymentFixtureCustomWETH()

const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");
const { createUniswapV3DeploymentFixtureCustomWETH } = require("@revxchain/uniswap-v3-utils/test/UniswapV3DeploymentFixture.js");

// your custom WETH's address
const wethAddress = "0x..."; 

// call function with custom WETH's address
const UniswapV3DeploymentFixtureCustomWETH = createUniswapV3DeploymentFixtureCustomWETH(wethAddress);

// initialize fixture
const {
    uniswapV3Deployer, uniswapFactory, descriptorLibrary, tokenDescriptor, nonfungiblePositionManager, 
    swapRouter01, swapRouter02, quoter01, quoter02, tickLens, multicall, multicall2, permit2, 
    universalRouter, uniswapV3PoolBytecode, uniswapV3PoolAbi
} = await loadFixture(UniswapV3DeploymentFixtureCustomWETH);

UniswapV3MainnetForkSetup()

const { UniswapV3MainnetForkSetup } = require("@revxchain/uniswap-v3-utils/test/UniswapV3DeploymentFixture.js");

const targetChainId = 1;

const {
    weth, uniswapFactory, descriptorLibrary, tokenDescriptor, nonfungiblePositionManager, 
    swapRouter01, swapRouter02, quoter01, quoter02, tickLens, multicall, multicall2, permit2, 
    universalRouter, uniswapV3PoolBytecode, uniswapV3PoolAbi
} = await UniswapV3MainnetForkSetup(targetChainId);

Security Considerations

  • No input validation. UniswapV3Utils does not verify the correctness of any input. Passing an address that is not a valid UniswapV3Pool, or a tokenIn that is not one of the pool's tokens, may result in silent zero returns rather than a revert. You MUST validate inputs externally.

  • TWAP manipulation resistance. The default TWAP window (DEFAULT_TWAP_AGE = 15 minutes) provides protection against single-block sandwich attacks, but longer windows provide stronger guarantees. Always assess the time window relative to your protocol's risk tolerance.

  • Spot price susceptibility. Functions that use the current tick (getAmountOut) or the force fallback path (getForceTimeWeightedAmountOut) are susceptible to price manipulation within the same block. Use with caution — never as the sole price oracle for financial decisions.

  • Fixed-point rounding and discrete tick logic. All calculations use integer fixed-point arithmetic with Q64.96 precision. In cases of very wide ranges, very narrow ranges, or extremely disproportionate token amounts, computed boundaries (getUpperSqrtPriceX96, getLowerSqrtPriceX96, getProportionalAmounts, getSqrtPriceX96) may differ significantly from a benchmark. Always verify remaining amounts (dust) after using this calculation for interaction. If your requirements allow for off-chain calculations, it's better to do it that way. This library is useful when full on-chain autonomy and minimal risk of functionality blocking are required.

  • Oracle observation history. getTimeWeightedAmountOut (without force) will revert if the pool does not have sufficient historical observations for the requested secondsAgo window. This is an expected UniswapV3 behaviour — ensure adequate observation cardinality before relying on TWAP.


License

MIT License

Permission is hereby granted to use, copy, modify, and distribute this software freely.

See LICENSE file for full terms.


Contributing

Contributions welcome! Please:

  1. Fork the repository;
  2. Create a feature branch;
  3. Add tests for new functionality;
  4. Submit a pull request.

Support