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

Allow Echidna & Medusa to share the same corpus #234

Open
aviggiano opened this issue Sep 19, 2023 · 6 comments
Open

Allow Echidna & Medusa to share the same corpus #234

aviggiano opened this issue Sep 19, 2023 · 6 comments
Labels
help wanted Extra attention is needed high-priority

Comments

@aviggiano
Copy link

Describe the desired feature

This is a feature request to standardize the corpus between https://github.com/crytic/echidna and https://github.com/crytic/medusa, so that it is easier to replay transactions from one tool on the other.

Ref: crytic/echidna#1123

@karmacoma-eth
Copy link

I think there is an opportunity to standardize on a simple common format. It would open up some interesting possibilities:

  • start in one tool, continue in the other as @aviggiano suggested
  • write new tools that generate a starting corpus or extend an existing corpus (like Optik)
  • write new tools that can process / analyze / compare corpuses across runs of a fuzzer and across fuzzers

I'd like to suggest a format inspired by https://github.com/ethereum/tests:
https://karmacoma.notion.site/Common-Corpus-Format-1d273a31ae4b43a4bc9f4df1e96fa900?pvs=4

I think I'd be pretty happy to work with this format but I'd love to hear what you think.

@aviggiano
Copy link
Author

I believe the whole industry would benefit from this standardization. CC @gakonst @mds1

@grandizzy
Copy link

grandizzy commented May 8, 2024

@karmacoma-eth wanted to make sure I properly understand your proposed format - for a scenario like:

target contract
contract TargetContract {
  function doSomething(uint256 x) external {}
}
test handler contract: modifies env, calls target, then modifies again env
contract TestHandler is Test {

    TargetContract target = new TargetContract();

    function work(uint256 x) external {
      vm.roll(block.number + 1);
      target.doSomething(x);
      vm.warp(block.number + 1);
    }
}

where the test execution would look something like

  [30977] TestHandler::work(3613300754934649 [3.613e15])
    ├─ [0] VM::roll(19812633)
    │   └─ ← [Return] 
    ├─ [189] TargetContract::doSomething(3613300754934649)
    │   └─ ← [Stop] 
    ├─ [0] VM::warp(19812634 [1.981e7])
    │   └─ ← [Return] 
    └─ ← [Stop] 

Should the call sequence include only the children txes as in

sequence
[
   {
      "to":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D",
      "data":"0x1f7b4f3000000000000000000000000000000000000000000000000000000000012e5119",
      "_info":"vm.roll(19812633)"
   },
   {
      "sender":"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f",
      "to":"0x104fbc016f4bb334d775a19e8a6510109ac63e00",
      "data":"0xa6b206bf000000000000000000000000000000000000000000000000000cd64723f6eb79",
      "_info":"TargetContract::doSomething(3613300754934649)"
   },
   {
      "to":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D",
      "data":"0xe5d6bf0200000000000000000000000000000000000000000000000000000000012e511a",
      "_info":"vm.warp(19812634)"
   }
]

or should also include the parent as in

sequence
{
   "sender":"0xeaa1ffc3f1012ad923577141ed582ab41d006934",
   "to":"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f",
   "data":"0x5858d161000000000000000000000000000000000000000000000000000cd64723f6eb79",
   "_info":"TestHandler::work(3613300754934649)",
   "calls":[
      {
         "to":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D",
         "data":"0x1f7b4f3000000000000000000000000000000000000000000000000000000000012e5119",
         "_info":"vm.roll(19812633)"
      },
      {
         "sender":"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f",
         "to":"0x104fbc016f4bb334d775a19e8a6510109ac63e00",
         "data":"0xa6b206bf000000000000000000000000000000000000000000000000000cd64723f6eb79",
         "_info":"TargetContract::doSomething(3613300754934649)"
      },
      {
         "to":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D",
         "data":"0xe5d6bf0200000000000000000000000000000000000000000000000000000000012e511a",
         "_info":"vm.warp(19812634)"
      }
   ]
}

(I assume 1st option?) thanks!

@karmacoma-eth
Copy link

karmacoma-eth commented May 13, 2024

@grandizzy there is a 3rd option (include only the top level call):

calls = [
  {
     "sender":"0xeaa1ffc3f1012ad923577141ed582ab41d006934",
     "to":"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f",
     "data":"0x5858d161000000000000000000000000000000000000000000000000000cd64723f6eb79",
     "_info":"TestHandler::work(3613300754934649)"
  }
]

I think this option is more correct, the idea is that we should only represent calls made by the driver to the test code. In this case, the driver has invoked TestHandler::work(3613300754934649), and the subcalls happened internally in TestHandler. If we do include the subcalls in the trace, it should only be informational.

In other words, the only thing necessary to replay the same result should be for the test driver to run the same setUp and then invoke TestHandler::work(3613300754934649) again

@grandizzy
Copy link

thank you, makes sense, will update support to use this format

@0xalpharush
Copy link
Contributor

0xalpharush commented May 14, 2024

We are still working on a draft of a standard that includes necessary info e.g. the ABI of TestHandler::work and will share with Foundry and Halmos soon for feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed high-priority
Projects
None yet
Development

No branches or pull requests

5 participants