0

I need to get a precise reading of the fees generated by a liquidity providing position I opened on Uniswap V3, and I need to get it on another smart contract (not on a frontend, so no use in considering APIs).

My steps have been:

  1. Created a pair of custom tokens on kovan testnet
  2. Created a liquidity pool using the two tokens on the official testnet Uniswap V3 (address 0xC36442b4a4522E871399CD717aBDD847Ab11FE88)
  3. Created a custom smart contract on which I am depositing my NFT. This smart contract must be able to access through a read function the unclaimed fees generated by the underlying position.

After an extensive research it does not seem to exist an official Uniswap function to read the unclaimed fees onchain, but by digging in their frontend code I realized that they calculate the user unclaimed fees by calling the collect function forcing read-only state through the STATICCALL opcode.

So I tried to replicate it in my smart contract in a view function but the STATICCALL call continues to fail.

Here is my relevant smart contract code:

[...]
IINonfungiblePositionManager NFPosManager = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
[...]
function getUnclaimedFeeBalanceOfNFT(uint256 objectId) public view returns (bool _success, bytes memory data) {

     (_success, data) = address(NFPosManager).staticcall(abi.encodeWithSelector(INonfungiblePositionManager.collect.selector, INonfungiblePositionManager.CollectParams({
          tokenId: objectId,
          recipient: address(this),
          amount0Max: type(uint128).max,
          amount1Max: type(uint128).max
     })));
       
     return (_success, data);
}

When calling the collect function in this manner (before depositing the NFT on my smart contract) the INonfungiblePositionManager smart contract receives the transaction but returns:

0:
bool: _success false
1:
bytes: data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c4e6f7420617070726f7665640000000000000000000000000000000000000000

The data field, decoded from bytes, is a 'Not approved' error generated by Uniswap NonfungiblePositionManager smart contract.

After having deposited the NFT on my smart contract, the return values changes in:

0:
bool: _success false
1:
bytes: data 0x

So no answer ...

Here are the link of the used Uniswap smart contract repo: https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol

Does anyone encounter the same problem? Am I doing something wrong? Is there another method to read the unclaimed fees onchain?

Thanks for the help!

1 Answer 1

0

For the 1st part, the collect function has the modifier

modifier isAuthorizedForToken(uint256 tokenId) {
        require(_isApprovedOrOwner(msg.sender, tokenId), 'Not approved');
}

with _isApprovedOrOwner being part of the ERC721 implementation (check OpenZeppelin doc).

So for a contract to call this function, even with a non-state changing staticcall, it needs to either be the owner or be approved.

For the 2nd part, it seems STATICCALL prevents modifying the state, and because collect tries to change state it reverts, as per EIP-214.

Afaik there's no way to know the UNI v3 fees from inside a smart contract without collecting them. Not sure why such a design it is indeed inconvenient.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.