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 reading deployedBytecode.object code object from JSON file #659

Merged
merged 6 commits into from
Feb 18, 2025

Conversation

msooseth
Copy link
Collaborator

@msooseth msooseth commented Feb 13, 2025

Description

Sometimes, as reported by users, the command line limit of 8k characters is too few for a contract. In these cases, it's actually impossible to run --symbolic of --equivalance. So for these cases, I created --code-file and --code-a-file and --code-b-file which can be given as an alternative. Then the .deployedBytecode.object object is read from the provided Forge JSON file.

Unfortunately, Forge JSON is not currently documented, and my understanding is that it's not documented because they want to be able to change it to meet their requirements. However, it's kind of a semi-default for many systems (e.g. also Halmos) to read Forge JSON files. I will open an issue at Forge to ask them about this JSON file's format.

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

@blishko
Copy link
Collaborator

blishko commented Feb 14, 2025

Can you write down, or reference, what is the structure of the JSON file?
Are there other fields in deployedBytecode than object?
I am just curious.

CHANGELOG.md Outdated Show resolved Hide resolved
@msooseth
Copy link
Collaborator Author

Can you write down, or reference, what is the structure of the JSON file? Are there other fields in deployedBytecode than object? I am just curious.

Yes, good point. So I actually can't really find any reference for this -- it seems to be by forge, for forge. It has actually broken our build before, because we use the JSON to read out e.g. the AST. And I can't seem to find a good description of this JSON format on forge's website. However, the most important two parts of it for us are:

  31   │   "bytecode": {
  32   │     "object": "0x608060405234801561000f575f80fd5b506101ae8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061003f575f3560e01c80630dbe671f1461004357806337
       │ 1303c014610061578063b1712ffd1461006b575b5f80fd5b61004b610075565b60405161005891906100be565b60405180910390f35b61006961007a565b005b610073610092565b005b5f5481565b5f808
       │ 1548092919061008b90610104565b9190505550565b60025f54036100a4576100a361014b565b5b565b5f819050919050565b6100b8816100a6565b82525050565b5f6020820190506100d15f8301846100
       │ af565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61010e826100a6565b91507ffffffffffffffffffffffffffffff
       │ fffffffffffffffffffffffffffffffffff82036101405761013f6100d7565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160
       │ 045260245ffdfea2646970667358221220cc4eca1d86d91f9e4e31adace6dd3e0dcce1464d1a7809d142710b77b9d7082a64736f6c63430008160033",
  33   │     "sourceMap": "109:149:26:-:0;;;;;;;;;;;;;;;;;;;",
  34   │     "linkReferences": {}
  35   │   },
  36   │   "deployedBytecode": {
  37   │     "object": "0x608060405234801561000f575f80fd5b506004361061003f575f3560e01c80630dbe671f14610043578063371303c014610061578063b1712ffd1461006b575b5f80fd5b61004b6100
       │ 75565b60405161005891906100be565b60405180910390f35b61006961007a565b005b610073610092565b005b5f5481565b5f8081548092919061008b90610104565b9190505550565b60025f54036100a
       │ 4576100a361014b565b5b565b5f819050919050565b6100b8816100a6565b82525050565b5f6020820190506100d15f8301846100af565b92915050565b7f4e487b71000000000000000000000000000000
       │ 000000000000000000000000005f52601160045260245ffd5b5f61010e826100a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036101405761013f6100d
       │ 7565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220cc4eca1d86d91f9e4e31adac
       │ e6dd3e0dcce1464d1a7809d142710b77b9d7082a64736f6c63430008160033",
  38   │     "sourceMap": "109:149:26:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157:42;;;:::i;:::-;;204:52;;;:::i;:::-;;135:16;;
       │ ;;:::o;157:42::-;189:1;;:3;;;;;;;;;:::i;:::-;;;;;;157:42::o;204:52::-;247:1;242;;:6;235:14;;;;:::i;:::-;;204:52::o;7:77:49:-;44:7;73:5;62:16;;7:77;;;:::o;90:118::-
       │ ;177:24;195:5;177:24;:::i;:::-;172:3;165:37;90:118;;:::o;214:222::-;307:4;345:2;334:9;330:18;322:26;;358:71;426:1;415:9;411:17;402:6;358:71;:::i;:::-;214:222;;;;::
       │ :o;442:180::-;490:77;487:1;480:88;587:4;584:1;577:15;611:4;608:1;601:15;628:233;667:3;690:24;708:5;690:24;:::i;:::-;681:33;;736:66;729:5;726:77;723:103;;806:18;;::
       │ :i;:::-;723:103;853:1;846:5;842:13;835:20;;628:233;;;:::o;867:180::-;915:77;912:1;905:88;1012:4;1009:1;1002:15;1036:4;1033:1;1026:15",
  39   │     "linkReferences": {}
  40   │   },

Where the bytecode is the code that, when run, will deploy the code. And the deployedBytecode is after deployment. Almost always we want the deployed bytecode, because the un-deployed one is only running the initalization, which is often default. I am currently working on a PR to allow running the init (i.e. creation) and compare the final deployed bytecode, see Zoe's work at #650 which I am working on top in the meanwhile.

So I decided to take the deployedBytecode because it seemed to have made the most sense, and that's what we use by default in all our systems. In general, that's what people are interested in. For example, the foundry tests are using that by default, with no other option:

-- | Reads a foundry json output
readFoundryJSON :: Text -> Text -> Err (Contracts, Asts, Sources)
readFoundryJSON contractName json = do
  runtime <- maybeToEither "missing 'deployedBytecode' field" $ json ^? key "deployedBytecode"
  runtimeCode <- maybeToEither "missing 'deployedBytecode.object' field" $
    (toCode contractName) . strip0x'' <$> runtime ^? key "object" % _String
  runtimeSrcMap <- case runtime ^? key "sourceMap" % _String of
    Nothing -> Right $ force "Source map creation error" $ makeSrcMaps ""  -- sourceMap is optional
    Just smap -> maybeToEither "invalid sourceMap format" $ makeSrcMaps smap

@msooseth
Copy link
Collaborator Author

Damn. Actually, we could reuse that function, readFoundryJSON. Would work for all the purposes that we have here. Damn. OK, let me re-write this PR. I'm an idiot.

@msooseth msooseth self-assigned this Feb 17, 2025
@msooseth
Copy link
Collaborator Author

OK, I'll rewrite this and ping you when I'm done. I'm sorry for this mess.

@msooseth msooseth changed the title Allow reading deployedBytecode.object code object from JSON file Allow reading deployedBytecode.object code object from JSON file (TODO: use readFoundryJSON) Feb 17, 2025
@msooseth
Copy link
Collaborator Author

OK, I had a look -- the alternative way of doing this, via readSolc is actually super-messy and does not get the work done in any better way. The setup here is actually better. So I won't re-write this to use that function, it's a lot more complicated, rather than less complicated, and does lead to a good user experience (they'd have to set the root, too, and the code would need sourceMap as well, which is not guaranteed, for example)

What do you think would be needed for this PR to be acceptable? Maybe some more documentation? Or better command line description? I see your point, but I am not sure what would be the best way to address it.

@msooseth msooseth changed the title Allow reading deployedBytecode.object code object from JSON file (TODO: use readFoundryJSON) Allow reading deployedBytecode.object code object from JSON file Feb 18, 2025
CHANGELOG.md Outdated Show resolved Hide resolved
cli/cli.hs Outdated Show resolved Hide resolved
cli/cli.hs Outdated Show resolved Hide resolved
cli/cli.hs Outdated Show resolved Hide resolved
Copy link
Collaborator

@blishko blishko left a comment

Choose a reason for hiding this comment

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

LGTM!

@msooseth msooseth merged commit f58463a into main Feb 18, 2025
9 checks passed
@msooseth msooseth deleted the file-read branch February 18, 2025 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants