Demo: Running a local Anvil devchain with core contracts in seconds

Demo: Running a local Anvil devchain with all core contracts

You can run a local anvil devchain with (most) core contracts using the latest @celo/devchain-anvil package.


Foundry allows you to start a local anvil instance with state you can read from a json file.

$ anvil --state <PATH>
    This is an alias for both --load-state and --dump-state.
    It initializes the chain with the state and block environment stored at the file, if it
    exists, and dumps the chain's state on exit.

Source: Anvil docs


We publish a small file (devchain.json) in the @celo/devchain-anvil package that contains state with pre-loaded core contracts like the Registry contract (at 0x000000000000000000000000000000000000ce10).

This file allows you to start an anvil instance in seconds that serves at localhost:8545 on your machine. Your local anvil instance comes pre-configured with core contracts, and lets you make the usual RPC calls, as if you were interacting with Celo on Alfajores or Mainnet.


  1. Make a test directory

    $ mkdir ~/Documents/celo-org/devchain-anvil-installation
    $ cd ~/Documents/celo-org/devchain-anvil-installation
  2. Install the @celo/devchain-anvil package

    $ npm install --save-dev @celo/devchain-anvil
  3. Start up anvil with the JSON state from the package

    $ anvil --state node_modules/@celo/devchain-anvil/devchain.json
                                 _   _
                                (_) | |
          __ _   _ __   __   __  _  | |
         / _` | | '_ \  \ \ / / | | | |
        | (_| | | | | |  \ V /  | | | |
         \__,_| |_| |_|   \_/   |_| |_|
        0.2.0 (f625d0f 2024-04-02T00:16:42.824772000Z)
    Available Accounts
    (0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000.000000000000000000 ETH)
  4. Now you can make RPC calls against

    # ...
    Listening on

For example:

  1. (in a separate terminal) Find any core contract address in the Registry using the getAddressForStringOrDie function (e.g. the Reserve contract)

    cast call \
    "0x000000000000000000000000000000000000ce10" \
    "getAddressForStringOrDie(string calldata identifier)(address)" \
    "Reserve" \
  2. (in a separate terminal) Check that 0x1A888D93eeAcF683c68E07Ad58Aa43f2A5742490 is a registered ReserveSpenderMultiSig on the Reserve contract

    cast call \
    "0xe5cC39E5404c451604A85a4CD9686d918D18577e" \
    "isSpender(address)(bool)" \
    "0x909158d6b441312D6813CBea21D466C66ef94280" \

Next steps

We are actively working on and improving the devchain, so if you have any requests let us know on GitHub:

:lady_beetle: File a bug report

:speech_balloon: Ask a question

:sparkles: Suggest a feature

:technologist: Contribute!