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

--extra-output metadata option outputs different metadata than the expected compilation JSON output with bytecode_hash = "ipfs" #1738

Closed
2 tasks done
joaquim-verges opened this issue May 26, 2022 · 12 comments
Assignees
Labels
C-forge Command: forge Cmd-forge-build Command: forge build T-bug Type: bug
Milestone

Comments

@joaquim-verges
Copy link

Component

Forge

Have you ensured that all of these are up to date?

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (4fcd7e0 2022-05-26T00:04:48.079145Z)

What command(s) is the bug in?

forge build

Operating System

macOS (Apple Silicon)

Describe the bug

When outputting the solc compilation metadata using --extra-output metadata or --extra-output-files metadata the resulting metadata is not matching the bytecode IPFS hash of the compiled contract.

To reproduce in a fresh project:

forge init
forge build --extra-output metadata

then inspect the json output in out/Contract.sol/Contract.json.

I've done the same setup with hardhat and raw solcjs, both produce the expected metadata that matches exactly the IPFS hash appended to the bytecode.

For the same, empty contract, here's the metadata that hardhat outputs:

{
  "compiler": { "version": "0.8.13+commit.abaa5c0e" },
  "language": "Solidity",
  "output": {
    "abi": [],
    "devdoc": { "kind": "dev", "methods": {}, "version": 1 },
    "userdoc": { "kind": "user", "methods": {}, "version": 1 }
  },
  "settings": {
    "compilationTarget": { "contracts/Contract.sol": "Contract" },
    "evmVersion": "london",
    "libraries": {},
    "metadata": { "bytecodeHash": "ipfs" },
    "optimizer": { "enabled": false, "runs": 200 },
    "remappings": []
  },
  "sources": {
    "contracts/Contract.sol": {
      "keccak256": "0x88c53f90b24a07c57711738987ddc81838a43c4ab7b6ce2986f1b470500ebe86",
      "license": "UNLICENSED",
      "urls": [
        "bzz-raw://58178e99c552a2042318a4be96c35abdda48f5a1537a5c5c27c234b5dda43f2f",
        "dweb:/ipfs/QmTgVWYsTQyBx7PsNtmUaryTF27cjLQseyk4sxYGChd5ui"
      ]
    }
  },
  "version": 1
}

and here's the metadata that forge outputs:

{
    "compiler": { "version": "0.8.13+commit.abaa5c0e" },
    "language": "Solidity",
    "output": {
      "abi": [],
      "devdoc": { "kind": "dev", "methods": {}, "version": 1 },
      "userdoc": { "kind": "user", "methods": {}, "version": 1 }
    },
    "settings": {
      "compilationTarget": {
        "/Users/joaquim/solidity_projects/foundry_metadata_tests/src/Contract.sol": "Contract"
      },
      "remappings": [
        ":ds-test/=/Users/joaquim/solidity_projects/foundry_metadata_tests/lib/forge-std/lib/ds-test/src/",
        ":forge-std/=/Users/joaquim/solidity_projects/foundry_metadata_tests/lib/forge-std/src/",
        ":src/=/Users/joaquim/solidity_projects/foundry_metadata_tests/src/"
      ],
      "optimizer": { "enabled": true, "runs": 200 },
      "metadata": { "bytecodeHash": "ipfs" },
      "outputSelection": {},
      "evmVersion": "london"
    },
    "sources": {
      "/Users/joaquim/solidity_projects/foundry_metadata_tests/src/Contract.sol": {
        "keccak256": "0x88c53f90b24a07c57711738987ddc81838a43c4ab7b6ce2986f1b470500ebe86",
        "urls": [
          "bzz-raw://58178e99c552a2042318a4be96c35abdda48f5a1537a5c5c27c234b5dda43f2f",
          "dweb:/ipfs/QmTgVWYsTQyBx7PsNtmUaryTF27cjLQseyk4sxYGChd5ui"
        ],
        "license": "UNLICENSED"
      }
    },
    "version": 1
  }

Both hardhat and solcjs output metadata with relative paths, but forge outputs absolute paths. This seems strange to me as this metadata is supposed to be used to help re-compile the contracts on other machines, absolute paths make no sense to me here.

I've looked at the ethers-rs source and have noticed the function: with_stripped_file_prefixes

This seems relevant to my problem, is it possible that forge is not calling this function to strip the base paths out of the compilation artifacts, therefore causing a mismatch between the IPFS hash of the metadata and the IPFS hash appended to the bytecode by the compiler?

Might be totally wrong on this, but it's my best guess.

Any help on figuring out this mystery would be greatly appreciated, I can provide sample test code to compare extracted IPFS hashes from bytecode and computed IPFS hashes from a file if it helps.

@joaquim-verges joaquim-verges added the T-bug Type: bug label May 26, 2022
@onbjerg onbjerg added this to Foundry May 26, 2022
@onbjerg onbjerg moved this to Todo in Foundry May 26, 2022
@sambacha
Copy link
Contributor

Try bytecodehash: none

@mattsse mattsse self-assigned this May 27, 2022
@mattsse
Copy link
Member

mattsse commented May 27, 2022

thanks for reporting

looks like gakonst/ethers-rs#1307 only fixed the problem partially.

@mattsse
Copy link
Member

mattsse commented May 27, 2022

Ref #1315

@mattsse
Copy link
Member

mattsse commented May 27, 2022

should be fixed by 1317

@onbjerg onbjerg added C-forge Command: forge Cmd-forge-build Command: forge build labels May 27, 2022
@onbjerg onbjerg moved this from Todo to May be solved in Foundry May 27, 2022
@joaquim-verges
Copy link
Author

joaquim-verges commented May 27, 2022

thanks for the quick turn around @mattsse ! Should I expect the ether-rs change to be pulled in the next forge nightly build?

@joaquim-verges
Copy link
Author

@mattsse what's the easiest way for me to test this fix?

@mattsse
Copy link
Member

mattsse commented May 28, 2022

we haven't bumped it yet on foundry

the easiest way would be to build it forge yourself with patched ethers is by following this: https://github.com/foundry-rs/foundry/blob/master/Cargo.toml#L52

then cargo build --bin forge --release and the binary will be in target/release/forge

@joaquim-verges
Copy link
Author

@mattsse Thank you! the metadata output now has relative paths has expected.

However, I'm still not getting a match between the output metadata IPFS hash and the IPFS hash appended to the bytecode by solc.

In my investigation, I found a few issues in ethers-rs related to json serialization/deserialization. I'm going to create a new issue over there with my findings, to keep the conversation focused.

Thank you again for your hard work.

@joaquim-verges
Copy link
Author

@mattsse FYI, opened gakonst/ethers-rs#1325 - the serialization of the compiler metadata output is altering its original contents, resulting in a different IPFS hash than the one that gets appended to the bytecode.

@onbjerg
Copy link
Member

onbjerg commented Jun 21, 2022

Is this solved?

@joaquim-verges
Copy link
Author

Just tested it today. The new rawMetadata field is now present in the output.

I would suggest writing a test comparing the raw metadata and the parsed one. There's still some differences. Last one i noticed is a missing settings.evmVersion field.

@onbjerg onbjerg added this to the v1.0.0 milestone Jul 1, 2022
@mattsse
Copy link
Member

mattsse commented Aug 3, 2022

closed by gakonst/ethers-rs#1365 which added metadata string as raw string

@mattsse mattsse closed this as completed Aug 3, 2022
Repository owner moved this from May be solved to Done in Foundry Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-forge Command: forge Cmd-forge-build Command: forge build T-bug Type: bug
Projects
Archived in project
Development

No branches or pull requests

4 participants