Contract Address Details

0xA1A60E03139B65CDA4f0d1d7AD833064bB3DFef2

Contract Name
UncollectedFeeHelper
Creator
0xd6cf49–0769d0 at 0xb2e832–caa7b1
Balance
0 ETN ( )
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
5478820
Contract name:
UncollectedFeeHelper




Optimization enabled
true
Compiler version
v0.8.26+commit.8a97fa7a




Optimization runs
500
Verified at
2024-09-30T15:55:42.093557Z

Constructor Arguments

0000000000000000000000003a7f64c57433555b23dac4409a0ac7e84275398d

Arg [0] (address) : 0x3a7f64c57433555b23dac4409a0ac7e84275398d

              

contracts/UncollectedFeeHelper.sol

// SPDX-License-Identifier: CC-BY-NC-ND-4.0
pragma solidity ^0.8.0;
import "./libraries/FullMath.sol";
import "./libraries/FixedPoint128.sol";

contract UncollectedFeeHelper {

    INonfungiblePositionManager private positionManager;
    IElectroSwapV3Factory internal v3Factory;

    constructor(address _positionManager) {
        positionManager = INonfungiblePositionManager(_positionManager);
        v3Factory = IElectroSwapV3Factory(positionManager.factory());
    }

    function getUncollectedFees(uint256 positionTokenId) public view returns (uint256 uncollectedFee0, uint256 uncollectedFee1) {
        
        (
            ,
            ,
            address token0,
            address token1,
            uint24 fee,
            int24 tickLower,
            int24 tickUpper,
            uint128 liquidity,
            uint256 feeGrowthInside0LastX128,
            uint256 feeGrowthInside1LastX128,
            ,
        ) = positionManager.positions(positionTokenId);

        // Fetch the pool address
        address poolAddress = v3Factory.getPool(token0, token1, fee);
        IElectroSwapV3Pool pool = IElectroSwapV3Pool(poolAddress);

        // Fetch current fee growth inside the tick range
        (,int24 tickCurrent,,,,,) = pool.slot0();

        // Fetch global fee growth accumulators
        uint256 feeGrowthGlobal0X128 = pool.feeGrowthGlobal0X128();
        uint256 feeGrowthGlobal1X128 = pool.feeGrowthGlobal1X128();

        // Fetch tick data for lower and upper ticks
        (,,uint256 feeGrowthOutside0LowerX128, uint256 feeGrowthOutside1LowerX128,,,,) = pool.ticks(tickLower);
        (,,uint256 feeGrowthOutside0UpperX128, uint256 feeGrowthOutside1UpperX128,,,,) = pool.ticks(tickUpper);

        // Calculate fee growth below and above
        uint256 feeGrowthBelow0X128 = (tickCurrent >= tickLower)
            ? feeGrowthOutside0LowerX128
            : feeGrowthGlobal0X128 - feeGrowthOutside0LowerX128;

        uint256 feeGrowthAbove0X128 = (tickCurrent < tickUpper)
            ? feeGrowthOutside0UpperX128
            : feeGrowthGlobal0X128 - feeGrowthOutside0UpperX128;

        uint256 feeGrowthBelow1X128 = (tickCurrent >= tickLower)
            ? feeGrowthOutside1LowerX128
            : feeGrowthGlobal1X128 - feeGrowthOutside1LowerX128;

        uint256 feeGrowthAbove1X128 = (tickCurrent < tickUpper)
            ? feeGrowthOutside1UpperX128
            : feeGrowthGlobal1X128 - feeGrowthOutside1UpperX128;

        // Calculate fee growth inside the position's range
        uint256 feeGrowthInside0X128 = feeGrowthGlobal0X128 - feeGrowthBelow0X128 - feeGrowthAbove0X128;
        uint256 feeGrowthInside1X128 = feeGrowthGlobal1X128 - feeGrowthBelow1X128 - feeGrowthAbove1X128;

        // Calculate uncollected fees
        uncollectedFee0 = FullMath.mulDiv(liquidity, feeGrowthInside0X128 - feeGrowthInside0LastX128, FixedPoint128.Q128);
        uncollectedFee1 = FullMath.mulDiv(liquidity, feeGrowthInside1X128 - feeGrowthInside1LastX128, FixedPoint128.Q128);
    }
} 


interface INonfungiblePositionManager {

    function positions(uint256 tokenId) external view returns (
        uint96 nonce,
        address operator,
        address token0,
        address token1,
        uint24 fee,
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity,
        uint256 feeGrowthInside0LastX128,
        uint256 feeGrowthInside1LastX128,
        uint128 tokensOwed0,
        uint128 tokensOwed1
    );

    function factory() external view returns (address factory);
}


interface IElectroSwapV3Factory {
    function getPool(address, address, uint24) external view returns (address);
}

interface IElectroSwapV3Pool {

    function slot0() external view returns (
        uint160 sqrtPriceX96,
        int24 tick,
        uint16 observationIndex,
        uint16 observationCardinality,
        uint16 observationCardinalityNext,
        uint8 feeProtocol,
        bool unlocked
    );

    function ticks(int24 tick) external view returns (
        uint128 liquidityGross,
        int128 liquidityNet,
        uint256 feeGrowthOutside0X128,
        uint256 feeGrowthOutside1X128,
        int56 tickCumulativeOutside,
        uint160 secondsPerLiquidityOutsideX128,
        uint32 secondsOutside,
        bool initialized
    );

    function feeGrowthGlobal0X128() external view returns (uint256);
    function feeGrowthGlobal1X128() external view returns (uint256);
}
        

contracts/libraries/FixedPoint128.sol

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.4.0;

/// @title FixedPoint128
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
library FixedPoint128 {
    uint256 internal constant Q128 = 0x100000000000000000000000000000000;
}
          

contracts/libraries/FullMath.sol

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

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = a * b
            // Compute the product mod 2**256 and mod 2**256 - 1
            // then use the Chinese Remainder Theorem to reconstruct
            // the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2**256 + prod0
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(a, b, not(0))
                prod0 := mul(a, b)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division
            if (prod1 == 0) {
                require(denominator > 0);
                assembly {
                    result := div(prod0, denominator)
                }
                return result;
            }

            // Make sure the result is less than 2**256.
            // Also prevents denominator == 0
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0]
            // Compute remainder using mulmod
            uint256 remainder;
            assembly {
                remainder := mulmod(a, b, denominator)
            }
            // Subtract 256 bit number from 512 bit number
            assembly {
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator
            // Compute largest power of two divisor of denominator.
            // Always >= 1.
            uint256 twos = (0 - denominator) & denominator;
            // Divide denominator by power of two
            assembly {
                denominator := div(denominator, twos)
            }

            // Divide [prod1 prod0] by the factors of two
            assembly {
                prod0 := div(prod0, twos)
            }
            // Shift in bits from prod1 into prod0. For this we need
            // to flip `twos` such that it is 2**256 / twos.
            // If twos is zero, then it becomes one
            assembly {
                twos := add(div(sub(0, twos), twos), 1)
            }
            prod0 |= prod1 * twos;

            // Invert denominator mod 2**256
            // Now that denominator is an odd number, it has an inverse
            // modulo 2**256 such that denominator * inv = 1 mod 2**256.
            // Compute the inverse by starting with a seed that is correct
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
            uint256 inv = (3 * denominator) ^ 2;
            // Now use Newton-Raphson iteration to improve the precision.
            // Thanks to Hensel's lifting lemma, this also works in modular
            // arithmetic, doubling the correct bits in each step.
            inv *= 2 - denominator * inv; // inverse mod 2**8
            inv *= 2 - denominator * inv; // inverse mod 2**16
            inv *= 2 - denominator * inv; // inverse mod 2**32
            inv *= 2 - denominator * inv; // inverse mod 2**64
            inv *= 2 - denominator * inv; // inverse mod 2**128
            inv *= 2 - denominator * inv; // inverse mod 2**256

            // Because the division is now exact we can divide by multiplying
            // with the modular inverse of denominator. This will give us the
            // correct result modulo 2**256. Since the precoditions guarantee
            // that the outcome is less than 2**256, this is the final result.
            // We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inv;
            return result;
        }
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            result = mulDiv(a, b, denominator);
            if (mulmod(a, b, denominator) > 0) {
                require(result < type(uint256).max);
                result++;
            }
        }
    }
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_positionManager","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"uncollectedFee0","internalType":"uint256"},{"type":"uint256","name":"uncollectedFee1","internalType":"uint256"}],"name":"getUncollectedFees","inputs":[{"type":"uint256","name":"positionTokenId","internalType":"uint256"}]}]
            

Deployed ByteCode

0x608080604052600436101561001357600080fd5b60003560e01c6363bcf8271461002857600080fd5b3461044e57602036600319011261044e57610180816024816001600160a01b036000541663133f757160e31b825260043560048301525afa9081156102e057600091828080948180938196829661045b575b5060646020926001600160a01b039262ffffff846001541691856040519889978896630b4c774160e11b88521660048701521660248501521660448301525afa80156102e057600090610416575b6001600160a01b039150169260405195633850c7bd60e01b875260e087600481885afa9687156102e057600097610385575b5060405163f305839960e01b815295602087600481895afa9687156102e057600097610351575b50604051634614131960e01b8152966020886004818a5afa9788156102e05760009861031a575b506040519263f30dba9360e01b845260020b91826004850152610100846024818b5afa80156102e0576024966000956000926102ec575b50610100906040519889809263f30dba9360e01b825260020b9c8d60048301525afa9283156102e05761021f6102459a61023f996102399860409f988f986102309961022a986fffffffffffffffffffffffffffffffff9c600096600094610291575b5090610224969761021f9594939260020b94851215968760001461028157945b1297881561027157955b1561026157965b1561025157509661064f565b61064f565b9c61064f565b9861064f565b94169384610672565b9461064f565b90610672565b82519182526020820152f35b9061025b9161064f565b9661064f565b61026b908261064f565b96610213565b61027b908b61064f565b9561020c565b61028b908c61064f565b94610202565b610224975061021f9594506102c190610100949392943d81116102d9575b6102b9818361054a565b8101906105dd565b505050509a92509050989495509796929091926101e2565b503d6102af565b6040513d6000823e3d90fd5b6101008097506103099293503d81116102d9576102b9818361054a565b50505050979250905095919061017f565b90976020823d602011610349575b816103356020938361054a565b810103126103465750519638610148565b80fd5b3d9150610328565b90966020823d60201161037d575b8161036c6020938361054a565b810103126103465750519538610121565b3d915061035f565b60e0979197813d60e01161040e575b816103a160e0938361054a565b8101031261040a576103b281610582565b506103bf60208201610596565b916103cc604083016105c1565b506103d9606083016105c1565b506103e6608083016105c1565b5060a082015160ff811603610346575060c061040291016105d0565b5095386100fa565b5080fd5b3d9150610394565b506020813d602011610453575b816104306020938361054a565b8101031261044e576104496001600160a01b0391610582565b6100c8565b600080fd5b3d9150610423565b965050955050505050610180813d8211610542575b8161047e610180938361054a565b8101031261040a5780516bffffffffffffffffffffffff81160361040a576104a860208201610582565b506104b560408201610582565b6104c160608301610582565b9060808301519362ffffff8516850361034657506104e160a08401610596565b916104ee60c08501610596565b9460206001600160a01b03606461050760e089016105a4565b94610100890151966105306101606101208c01519b61052961014082016105a4565b50016105a4565b5090949799959698979250925061007a565b3d9150610470565b90601f8019910116810190811067ffffffffffffffff82111761056c57604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361044e57565b51908160020b820361044e57565b51906fffffffffffffffffffffffffffffffff8216820361044e57565b519061ffff8216820361044e57565b5190811515820361044e57565b91908261010091031261044e576105f3826105a4565b91602081015180600f0b810361044e579160408201519160608101519160808201518060060b810361044e579161062c60a08201610582565b9160c082015163ffffffff8116810361044e5760e061064c9193016105d0565b90565b9190820391821161065c57565b634e487b7160e01b600052601160045260246000fd5b60009160001981830991818102938480851094039380850394146106b75783600160801b1115610346575090600160801b910990828211900360801b910360801c1790565b5050505060801c9056fea2646970667358221220e74641c5e6bb55e69fcaf681ab2010129ec6fe297d98418b25e76d4c752ad6ce64736f6c634300081a0033