wevm / wagmi

Reactive primitives for Ethereum apps
https://wagmi.sh
MIT License
5.98k stars 1.06k forks source link

[bug] useContractReads always returning a [null] #642

Closed magiclars-off closed 2 years ago

magiclars-off commented 2 years ago

Is there an existing issue for this?

Package Version

0.5.5

Current Behavior

Trying to read one or multiple contracts using useContractReads always returns [null]

input:

import { erc721ABI, useContractReads } from 'wagmi';

[{
        addressOrName: '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d',
        contractInterface: erc721ABI,
        functionName: 'tokenURI',
        args: 1,
        chainId: 1,
}]

Same object does succeed with useContractRead

image

Expected Behavior

No response

Steps To Reproduce

No response

Link to Minimal Reproducible Example (CodeSandbox, StackBlitz, etc.)

No response

Anything else?

No response

jxom commented 2 years ago

I created a minimal CodeSandbox and could not reproduce this issue. Maybe check if the ABI at the contract address matches the ABI that you specified?

Here is my CodeSandbox demonstrating the same thing but with the Loot contract:

https://codesandbox.io/s/dreamy-river-0uer8i?file=/src/App.js

matthewlilley commented 2 years ago

@jxom I was having the same issue migrating a very basic hook to wagmi multicall from redux multicall. At first I thought probably just human error, but after some time I can't see anything obviously wrong here. Old returns expected data, new returns [null] or undefined consistently.

Screenshot_272

matthewlilley commented 2 years ago

I'll fork your code sandbox and hard code the data so you can see there is defintiely an issue here.

magiclars-off commented 2 years ago

I think the issues lies in my client being chain-aware

Not sure if that functionality is deprecated.. In the docs I cannot find the reference to it when following the link https://wagmi.sh/docs/client#provider-optional.

useContractReads only seems to work when the client isn't chain aware

JohnSmithyy commented 2 years ago

I'm actually facing this exact same issue. useContractReads will randomly stop working and start returning null values.

Looking in my browser console, I do see that it says multicall is not supported on my local network which is fine because I assume that if it can't do a multicall, it will just do each contract read in the reads function one after the other instead of a batch.

But not sure why it stops working all together randomly. My minimal example is pretty similar to what OP posted except I don't pass in a chainid.

JohnSmithyy commented 2 years ago

I am curious how #645 got resolved.

jxom commented 2 years ago

@JohnSmithyy – got a codesandbox you can push up that reproduces this issue?

JohnSmithyy commented 2 years ago

@JohnSmithyy – got a codesandbox you can push up that reproduces this issue?

Unfortunately not since I cannot replicate the issue consistently on a codesandbox. It happens randomly on my local network, not sure why. I'm thinking it has something to do with multicall since moving to useContractRead for each function works without issues but useContractReads will return null values randomly time to time.

I've tried specifying the multicall contract/blocknumber since I'm forking the mainnet but it doesn't like to cooperate for some reason.

JohnSmithyy commented 2 years ago

For example here is my localchain setup (using rainbowkit):

const localChain: Chain = {
  id: 31337,
  name: "Local",
  network: "local",
  nativeCurrency: {
    decimals: 18,
    name: "Local",
    symbol: "ETH",
  },
  rpcUrls: {
    default: "http://127.0.0.1:8545/",
  },
  testnet: false,
  multicall: {
    address: "0x5ba1e12693dc8f9c48aad8770482f4739beed696",
    blockCreated: 12336033,
  },
};

This does not work at all. I have to remove the multicall param for things to work.

ricardopinto commented 2 years ago

Experiencing the same issue with useContractInfiniteReads() on a local chain, without multicall support on this chain. Wagmi randomly returns null entries in the data.pages[0] array

jxom commented 2 years ago

Can you provide a minimal reproducible example?

ricardopinto commented 2 years ago

It's not reproducible 100% of the time but I can explain the setup:

  1. Created an ERC721 contract exposing a function like getNFTDataByID(uint256 id) public view returns(NFTData memory), and minted ~900 of these.

  2. On the frontend used wagmi like this to list all of them:

    const contractConfig = {
        addressOrName: "0xaddress_goes_here",
        contractInterface: "<abi_goes_here>",
    }
    const perPage: number = 1000
    const { data } = useContractInfiniteReads({
        cacheKey: 'nftDataCache',
        ...contractConfig,
        ...paginatedIndexesConfig(
            (index) => {
                console.log('index', index)
                return {
                ...contractConfig,
                functionName: 'getNFTDataByID',
                args: [index],
            }},
            { start: 900, perPage: perPage, direction: 'decrement' },
        ),
        suspense: true,
    })
  3. Randomly data.pages[0] array has some null entries

Hope it helps

Deg3n3rate commented 2 years ago

@JohnSmithyy Happened to run into a similar issue and just wanted to point out that wagmi is using Multicall3 under the hood as can be shown here: https://github.com/wagmi-dev/wagmi/blob/main/packages/core/src/actions/contracts/multicall.ts#L89

and you're specifying a Multicall2 address in your chain config. Multicall3 Implementation on eth mainnet can be found here: https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code

Hope this helps

ricardopinto commented 2 years ago

Great call out @Deg3n3rate . I didn't have any multicall deployed on my private network and it still worked, although slow, with that issue happening randomly. Yesterday after digging deeper into that same code I noticed the dependency on Multicall3, so I searched around and found an implementation that works wonders here: https://github.com/NFEL/multicall-python-clinet/blob/master/src/Multicall3.sol . Since the deployment of Multicall3, the null issue has not manifested again yet.

Hope it helps anyone coming across this

JohnSmithyy commented 2 years ago

@JohnSmithyy Happened to run into a similar issue and just wanted to point out that wagmi is using Multicall3 under the hood as can be shown here: https://github.com/wagmi-dev/wagmi/blob/main/packages/core/src/actions/contracts/multicall.ts#L89

and you're specifying a Multicall2 address in your chain config. Multicall3 Implementation on eth mainnet can be found here: https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code

Hope this helps

Thanks for your reply.

I've noticed this too but I'm forking mainnet off a specific block so I had to resort to using Multicall2 instead since Multicall3 does not exist yet.

JohnSmithyy commented 2 years ago

Great call out @Deg3n3rate . I didn't have any multicall deployed on my private network and it still worked, although slow, with that issue happening randomly. Yesterday after digging deeper into that same code I noticed the dependency on Multicall3, so I searched around and found an implementation that works wonders here: https://github.com/NFEL/multicall-python-clinet/blob/master/src/Multicall3.sol . Since the deployment of Multicall3, the null issue has not manifested again yet.

Hope it helps anyone coming across this

I'll give this a try. Did you just deploy Multicall3 to your local network and then specify it in the chain configuration?

ricardopinto commented 2 years ago

@JohnSmithyy that was precisely what I did. If I ever run into the same null issue I'll write down here.

JohnSmithyy commented 2 years ago

@ricardopinto

Could you share your local network configuration?

I have multicall3 setup but now just returns stale data instead of nulls. So when I do a deposit on my contract, it still shows the previous / old balance instead.

ricardopinto commented 2 years ago

@JohnSmithyy it goes something like this:

const myTestnetChain: Chain = {
  id: 7200,
  name: 'My Testnet',
  network: 'my-testnet',
  iconUrl: null,
  iconBackground: '#fff',
  nativeCurrency: {
    decimals: 18,
    name: 'ETH',
    symbol: 'ETH',
  },
  rpcUrls: {
    default: 'https://my.testnet.local',
  },
  blockExplorers: {
    default: {
      name: "WinrScan",
      url: 'https://myscan.testnet.local/'
    },
  },
  multicall: {
    address: "0xaddress_goes_here",
    blockCreated: 123456,
  },
  testnet: true,
};
JohnSmithyy commented 2 years ago

Yeah that matches my setup too @ricardopinto

Weird that it doesn't work. Are you also forking mainnet?

ricardopinto commented 2 years ago

@JohnSmithyy No forking, just a simple private network using geth.

JohnSmithyy commented 2 years ago

Interesting. I'm using a hardhat node/workflow.

github-actions[bot] commented 9 months ago

This issue has been locked since it has been closed for more than 14 days.

If you found a concrete bug or regression related to it, please open a new bug report with a reproduction against the latest wagmi version. If you have any other comments you can create a new discussion.