Search code examples
ethereumchainlinkganachebrownie

How to reference LINK token on (forked) development network without "invalid opcode"?


I like to run a number of local tests. Everything works well on rinkeby and other test chains. However, the local development chain disagrees with my configuration. When I run a forked development network:

brownie console --network mainnet-fork

The ganache-cli initiates as expected:

Brownie v1.18.1 - Python development framework for Ethereum

BlockchainProject is the active project.

Launching 'ganache-cli --accounts 10 --hardfork istanbul --fork https://mainnet.infura.io/v3/6a633a4ecae8449abbc69974cdd3a9b9 --gasLimit 12000000 --mnemonic brownie --port 8545 --chainId 1'...
Brownie environment is ready.

However, even the most simple contract interaction fails:

>>> link_token = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
Fetching source of 0x514910771AF9Ca656af840dff83E8264EcF986CA from api.etherscan.io...
>>> accounts[0].balance()
100000000000000000000
>>> accounts[1].balance()
100000000000000000000
>>> link_token.transfer(accounts[0].address, 100, {'from': accounts[0].address})
Transaction sent: 0x1542b679e4d09b2f4523427c7f5048ed01ee0d194c34cd27b82bbd177e1b3f23
  Gas price: 0.0 gwei   Gas limit: 12000000   Nonce: 2
  LinkToken.transfer confirmed (invalid opcode)   Block: 14604608   Gas used: 12000000 (100.00%)

<Transaction '0x1542b679e4d09b2f4523427c7f5048ed01ee0d194c34cd27b82bbd177e1b3f23'>

Since the Link token is compiled with an unsupported compiler I do not get any further information on why this results in LinkToken.transfer confirmed (invalid opcode).

How do I (correctly) run chainlink code against a forked development network using brownie - am I missing a step such as funding??

My networks: configuration in brownie-config.yaml:

networks:
  mainnet-fork:
    vrf_coordinator: '0xf0d54349aDdcf704F77AE15b96510dEA15cb7952'
    link_token: '0x514910771AF9Ca656af840dff83E8264EcF986CA'
    keyhash: '0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445'

I did try to rm -rf build but that does not change anything.

System environment:

  • Brownie v1.18.1
  • Node 8.5.5
  • Ganache v7.0.4
  • 21.3.0 Darwin Kernel Version (macOS 12.2.1)
  • Python 3.9.7

Solution

  • In this instance, the account used for Link token funding does not have any Link. For some reason, the transaction does not get reverted but the unlock: option of brownie provides assistance.

    First adjusting the networks:settings to include an arbitrary account with a large Link balance:

      mainnet-fork:
        cmd_settings:
          unlock:
            - 0xf37c348b7d19b17b29cd5cfa64cfa48e2d6eb8db
        vrf_coordinator: '0xf0d54349aDdcf704F77AE15b96510dEA15cb7952'
        link_token: '0x514910771AF9Ca656af840dff83E8264EcF986CA'
        keyhash: '0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445'
    

    Second, run a mainnet-fork as before:

    brownie console --network mainnet-fork
    

    Third, confirm that the unlocked account is available and funded:

    >>> accounts[10]
    <Account '0xF37C348B7d19b17B29CD5CfA64cfA48E2d6eb8Db'>
    >>> accounts[10].balance()
    426496436000000000
    

    Fourth, instantiate the contract of the token, Link in this instance:

    link_token = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
    

    Finally, transfer Link from the unlocked account to some other account (or contract):

    link_token.transfer(accounts[0], 20, {"from": accounts[10]})
    

    Alternatively, funding the mainnet address with Link, or even unlocking the Link owner and minting new Link would work too...