---
# System prepended metadata

title: GFX Labs UniswapV3 Limit Order Product

---

## How it works

GFX Labs' Uniswap V3 product presents a decentralized limit order service that capitalizes on Uniswap V3's concentrated liquidity mechanism. This unique feature of Uniswap V3 can be leveraged to function as a limit order trading platform against the liquidity pool, providing that concentrated liquidity is committed to a future, densely populated tick.

Once this tick is reached, the pool instantly swaps one asset for another, allowing users to claim directly from the pool. However, there's a caveat: if users do not claim their position in time, it will revert back to a single asset.

To counter this issue, GFX Labs utilizes the Chainlink Keepers feature. These Keepers monitor the ticks, and when any trade tick is satisfied in the V3 pool, they execute transactions ensuring all trades are fulfilled at the correct times. Consequently, users can confidently claim their tokens from the GFX Labs contract.

Consequently, users can confidently claim their tokens from the GFX Labs contract. GFX Labs charges a fee from the users' claimed orders to compensate for the Chainlink Keeper service they are running. This fee is collected at the point when users claim their tokens from the contract.


## Findings in the codebase

**Fee is wrongly calculated when the token to be claimed/traded is WETH**

The fee collected by the contract owner can be either in ETH or WETH form. The owner can claim this WETH from the contract at any time by invoking the following function:


```solidity
function withdrawNative() external onlyOwner {
        uint256 wrappedNativeBalance = WRAPPED_NATIVE.balanceOf(address(this));
        uint256 nativeBalance = address(this).balance;
        // Make sure there is something to withdraw.
        if (wrappedNativeBalance == 0 && nativeBalance == 0) revert LimitOrderRegistry__ZeroNativeBalance();

        // transfer wrappedNativeBalance if it exists
        if (wrappedNativeBalance > 0) WRAPPED_NATIVE.safeTransfer(owner, wrappedNativeBalance);
        // transfer nativeBalance if it exists
        if (nativeBalance > 0) owner.safeTransferETH(nativeBalance);
    }
```

This function transfers the entire WETH balance of the contract. However, this might lead to an issue where users' claimable WETH balances, idle in the contract, could inadvertently be deducted.

For instance, suppose a user created an order with $2000 in USDC at a tick, and upon reaching that tick, they are to receive 1 WETH. When the tick is reached and keepers execute the trade, the contract now holds 1 WETH, ready for the user to claim. However, due to the current configuration, the owner could inadvertently withdraw this WETH while collecting swap fees, as the fee calculation considers the contract's total balance.