Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding overrides object to useCall hook, breaks and throws error #1011

Closed
gsteenkamp89 opened this issue Oct 24, 2022 · 4 comments
Closed

Adding overrides object to useCall hook, breaks and throws error #1011

gsteenkamp89 opened this issue Oct 24, 2022 · 4 comments
Labels
bug Something isn't working

Comments

@gsteenkamp89
Copy link
Contributor

gsteenkamp89 commented Oct 24, 2022

Describe the bug
When adding overrides object to the useCall hook, there is an error thrown. Not adding the overrides produces the desired result, but I am unable to add a "from" address to the call.

This works:

  const { account } = useEthers();
  const { value, error } =
    useCall(
      account && {
        contract: reignTokenContract,
        method: 'getStakingAmount',
        args: [account],
      }
    ) ?? {};

This does not. It returns undefined.

  const { account } = useEthers();
  const { value, error } =
    useCall(
      account && {
        contract: reignTokenContract,
        method: 'getStakingAmount',
        args: [account, { from : account }],
      }
    ) ?? {};

The error in console:

Invalid contract call:
address=0x07f20dAbe6DA77858b81e2b08c555477268bd92A method=getStakingAmount args=0xC54070dA79E7E3e2c95D3a91fe98A42000e65a48,[object Object]

To Reproduce
call a view function using useCall. Check resuult. then call again with overrides object { from : "SOME_ADDRESS" }

Software versions

  • useDapp v1.1.5
  • Package manager YARN
  • Node version v16.15.1
@gsteenkamp89 gsteenkamp89 added the bug Something isn't working label Oct 24, 2022
@jakvbs
Copy link
Contributor

jakvbs commented Oct 25, 2022

Hi @gsteenkamp89, what is the purpose of adding the overrides object in this case?

@gsteenkamp89
Copy link
Contributor Author

Hi @gsteenkamp89, what is the purpose of adding the overrides object in this case?

In my case, the view function (somewhat erroneously imo) uses msg.sender while performing some sort of computation.
And not having a from address specified means the result of the calculation is incorrect. Consider this example:

    function getNetAmount(address user) external view returns (uint256 memory _amount) {
        uint256 _amount = amounts[user].totalAmount - amounts[msg.sender].expenses
        return _amount;
    }

Here the author of the contract should've used user instead of msg.sender, but that's another issue entirely.
My point is shouldn't we always be able to add override object to any contract interaction whether it's a write or just a read? I don't believe this is a limitation of multicall, but I might be wrong...

@jakvbs
Copy link
Contributor

jakvbs commented Oct 26, 2022

I realized that this problem has occurred before and was raised here. Unfortunately, we currently know that it cannot be done if the call is going through Multicall. The only solution at this point is to call the method directly on the contract instance like in this example:

  const [balance, setBalance] = useState('0')
  const { account, library } = useEthers()
  const contract = new Contract(wethAddress, wethInterface, library)

  useEffect(() => {
    const getBalance = async () => {
      if (account) {
        const currentBalance = await contract.balanceOf(account, {
          from: account,
        })
        setBalance(currentBalance.toString())
      }
    }
    void getBalance()
  }, [account, contract])

You can also use useBlockNumber hook which is available in @usedapp/core and pass its result to the dependency array in useEffect hook to make sure that the balance is updated on every block.

@jakvbs jakvbs closed this as completed Oct 26, 2022
@gsteenkamp89
Copy link
Contributor Author

I realized that this problem has occurred before and was raised here. Unfortunately, we currently know that it cannot be done if the call is going through Multicall. The only solution at this point is to call the method directly on the contract instance like in this example:

  const [balance, setBalance] = useState('0')
  const { account, library } = useEthers()
  const contract = new Contract(wethAddress, wethInterface, library)

  useEffect(() => {
    const getBalance = async () => {
      if (account) {
        const currentBalance = await contract.balanceOf(account, {
          from: account,
        })
        setBalance(currentBalance.toString())
      }
    }
    void getBalance()
  }, [account, contract])

You can also use useBlockNumber hook which is available in @usedapp/core and pass its result to the dependency array in useEffect hook to make sure that the balance is updated on every block.

This is exactly what I ended up doing 😅
I didn't realise this was a multicall issue. I really appreciate the feedback, thank you! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants