Skip to content

feat: forge verify-bytecode <address> to verify that code at a commit hash matches on-chain code #6893

@mds1

Description

@mds1

Component

Forge

Describe the feature you would like

Motivation

Users often want to make sure that bytecode at an address can be tied to a certain git commit. Common use cases of this are:

  1. Verifying that the code from the fix commit of an audit or security review matches the code that was actually deployed.
  2. Verifying that the code of a repo commit being proposed in a governance proposal matches the code that was actually deployed.

It's a lot of work for a contract verification service to also validate that the code being verified exists at a given commit, for all frameworks and languages. But it is easy for frameworks themselves to implement this feature on a case by case basis.

Solution

A new feature named forge verify-bytecode <address> (open to other names) to execute this check. It has the following syntax:

forge verify-bytecode <address> \
    [--block <blockTag>] \
    [--constructor-args <args> | --constructor-args-path <path> | --guess-constructor-args] \
    [--verification-type <full | partial>] \
    [--rpc-url <rpcUrl>]

And it behaves as follows:

  1. User clones some repo and checks out a commit.
  2. User executes forge verify-bytecode <address>.
    1. Similar to cast, ETH_RPC_URL is used as the default RPC, but an alternative can be provided using the --rpc-url flag.
    2. They can also optionally specify a build profile, or any other CLI flags allowed during forge build.
  3. Forge fetches the runtime bytecode at that address on the given chain. It also fetches the creation code from Etherscan or another verification service. This gives us the bytecodes we want to verify against.
  4. Forge compiles the repo using the given config. It now has build artifacts.
  5. Forge needs constructor arguments for the creation code. These can be obtained in multiple ways, in order of what should be preferred:
    1. User provides --constructor-args or --constructor-args-path, or uses --guess-constructor-args (from feat(forge verify-contract): --guess-constructor-args #6724)
    2. Constructor arguments are fetched from Etherscan/verification service.
  6. Creation code check can now be performed by appending the constructor arguments to the generated creation code and checking for a match. The metadata hash check defaults to using what’s specified in the build profile, but can be overridden with the --verification-type flag
  7. Runtime code check can now be performed by executing deployment of the creation code on a fork of the RPC URL. Metadata hash check is the same as above. For block number, in order of what should be preferred:
    1. If the user provided a --block <blockTag> arg, fork from the RPC at that block and simulate to get the runtime code.
    2. If the verification service returns the block number of deployment, use that

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Completed

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions