Skip to content

feat(cast): Run Arbitrary Bytecode#945

Closed
refcell wants to merge 8 commits intofoundry-rs:masterfrom
refcell:ab/forge_run_bytecode
Closed

feat(cast): Run Arbitrary Bytecode#945
refcell wants to merge 8 commits intofoundry-rs:masterfrom
refcell:ab/forge_run_bytecode

Conversation

@refcell
Copy link
Contributor

@refcell refcell commented Mar 15, 2022

Overview

This PR introduces a new subcommand for cast: run.

Motivation

Execute arbitrary bytecode using cast like the hevm exec command.

Solution Checklist

  • Eat Bytecode
  • Pass Bytecode into the EVM
  • Return Pretty Results

@gakonst
Copy link
Member

gakonst commented Mar 15, 2022

I like this directionally. It can be very powerful with forked mode.

One idea:

  1. What if we put this in cast so that it's similar to seth run-tx, behind cast run or cast exec?
  2. Should we add this functionality behind cast send --simulate as well, so that it runs a transaction against mainnet fork state?
  3. Should we also allow passing a <txhash> which would simulate a forked transaction locally?

This would allow us to print traces when simulating transactions, which would be quite useful for people doing on-chain forensics and whatnot, given that ethtx.info does not exist for other chains, and people end up using e.g. Tenderly's tracer/flamegraph

@refcell
Copy link
Contributor Author

refcell commented Mar 15, 2022

Open to making it a subcommand in cast, though I do believe @onbjerg makes a good argument that cast does not have any EVM context and this could bloat cast:
https://github.com/gakonst/foundry/issues/899#issuecomment-1065912974

@gakonst
Copy link
Member

gakonst commented Mar 15, 2022

Ah yes, but imagine that someone doing operations against mainnet wouldn't be using forge, they'd be using cast right? So if the exec bytecode use case is in the context of doing ops, it makes sense to bundle it in cast? So I'd err towards putting it there, and reconsider if we see the binary bloating (altho couple megabytes added should be fine)?

Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking god so far.

on cast/forge, since both live in the same crate, we can use commands in both cast and forge, perhaps we can restructure the cmd mod into

mod shared; mod forge; mod cast


#[derive(Debug, Clone, Parser)]
pub struct ExecArgs {
#[clap(help = "the bytecode to execute")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add note about expected format, hex

@onbjerg onbjerg added the T-feature Type: feature label Mar 17, 2022
@tynes
Copy link
Contributor

tynes commented Mar 18, 2022

3. Should we also allow passing a <txhash> which would simulate a forked transaction locally?

This would allow us to print traces when simulating transactions, which would be quite useful for people doing on-chain forensics and whatnot, given that ethtx.info does not exist for other chains, and people end up using e.g. Tenderly's tracer/flamegraph

I'm a big fan of this idea, would prefer to use local + scriptable tooling over tenderly. I think one gotcha would be that if a tx hash is passed, then all previous txs in the block would need to be fetched and executed first in case a previous tx in the block altered the same state that the passed tx touches

@mds1
Copy link
Collaborator

mds1 commented Mar 18, 2022

I'm a big fan of this idea, would prefer to use local + scriptable tooling over tenderly. I think one gotcha would be that if a tx hash is passed, then all previous txs in the block would need to be fetched and executed first in case a previous tx in the block altered the same state that the passed tx touches

Yea good call, this is how seth debug <txHash> behaves, though in practice the execution of the previous txs with HEVM was too slow so I'd mainly just use seth run-tx <txHash> --trace or seth run-tx <txHash> --debug which skips the execution of prior txs.

I think we should follow a similar pattern, and since there's a lot of overlap in the various seth/hevm commands, my proposal to clean up the API would be:

  1. Keep forge as the test runner (i.e. no changes to forge here)
  2. In this PR, setup cast run so it can execute arbitrary bytecode like hevm exec
  3. In future PRs, update cast run to:
    1. Accept transaction hashes (instead of just bytecode)
    2. Support both --trace and --debug modes
    3. When passing a tx hash, execute previous txs in the block by default unless a flag is passed to skip execution of those txs. Potential names for that flag are --unsound, --unsafe, --rapid, --quick
    4. For all touched addresses, pull from Etherscan by default for better traces/debugging, but also allow a --source or similar flag to pass the path to a forge directory containing contracts that should be compiled and referenced in the trace (e.g. for when a contract is not verified on Etherscan but you have it locally)

@refcell refcell changed the title feat(forge): Exec Arbitrary Bytecode feat(cast): Run Arbitrary Bytecode Mar 21, 2022
@refcell
Copy link
Contributor Author

refcell commented Mar 22, 2022

@refcell refcell closed this Mar 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-feature Type: feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants