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

Hardhat and foundry, contract compile bytecode different #5559

Closed
2 tasks
congtanwkm opened this issue Aug 8, 2023 · 4 comments
Closed
2 tasks

Hardhat and foundry, contract compile bytecode different #5559

congtanwkm opened this issue Aug 8, 2023 · 4 comments
Labels
T-bug Type: bug

Comments

@congtanwkm
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 (394f217 2023-03-21T00:11:00.708322Z)

What command(s) is the bug in?

forge test

Operating System

None

Describe the bug

I'm developing contracts on a hardhat project, and I want to write test for it by foundry. The problem I'm facing is: In my contract, I will create a new child contract with the same salt + constructor params, but when running it on foundry and hardhat, it provides different addresses. After looking for the issue, I found that bytecode of child contract from foundry and hardhat is not the same, it means the bytecode which is compiled by foundry (in out) and hardhat (in artifacts) are different. My test in hardhat worked well, I can predict the child contract address by ethers.utils.getCreate2Address in js.

I wonder if there is any difference between the hardhat config and foundry toml, but after many try with many kinds of config, the problem is still there.
Is there any way to ensure that the config of hardhat and foundry execute the same.

This is my smart contract code:

contract Parent {

  function born(bytes32 id, string memory name, uint256 weight) external  returns(address) {
      Child child = new Child{salt: id}(name, weight);
      return address(child);
  }
}

hardhat config:

config = {
  solidity: {
    version: "0.8.18",
    evmVersion: "london",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200,
      },
    },
  }
...
}

foundry config

[profile.default]
src = 'contracts'
out = 'out'
libs = ['node_modules', 'lib']
test = 'test/foundry'
cache_path  = 'forge-cache'
gas_reports = ["*"]
optimizer = true
optimizer_runs = 200
solc = "0.8.18"
evm_version = "london"
auto_detect_solc = false

Forge version: 0.2.0
Hardhat version: 2.14.0

@congtanwkm congtanwkm added the T-bug Type: bug label Aug 8, 2023
@gakonst gakonst added this to Foundry Aug 8, 2023
@github-project-automation github-project-automation bot moved this to Todo in Foundry Aug 8, 2023
@mattsse
Copy link
Member

mattsse commented Aug 9, 2023

which is compiled by foundry (in out) and hardhat (in artifacts) are different.

different how? metadata hash?

@congtanwkm
Copy link
Author

congtanwkm commented Aug 10, 2023

different how? metadata hash?

You can see the image, both bytecode from hardhat and foundry has the same length, but different ~30 bytes near the end

image

@congtanwkm
Copy link
Author

I tried another simple contract which has shorter bytecode. This is contract code:

pragma solidity 0.8.18;
contract Lock {
    uint256 public unlockTime;
    address payable public owner;
    event Withdrawal(uint256 amount, uint256 when);

    constructor(uint256 _unlockTime) payable {
        require(block.timestamp < _unlockTime, "Unlock time should be in the future");
        unlockTime = _unlockTime;
        owner = payable(msg.sender);
    }
    function withdraw() public {
        require(block.timestamp >= unlockTime, "You can't withdraw yet");
        require(msg.sender == owner, "You aren't the owner");
        emit Withdrawal(address(this).balance, block.timestamp);
        owner.transfer(address(this).balance);
    }
}

Hardhat compiled bytecode:

0x60806040526040516102a53803806102a58339810160408190526100229161009b565b8042106100815760405162461bcd60e51b815260206004820152602360248201527f556e6c6f636b2074696d652073686f756c6420626520696e207468652066757460448201526275726560e81b606482015260840160405180910390fd5b600055600180546001600160a01b031916331790556100b4565b6000602082840312156100ad57600080fd5b5051919050565b6101e2806100c36000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063251c1aa3146100465780633ccfd60b146100625780638da5cb5b1461006c575b600080fd5b61004f60005481565b6040519081526020015b60405180910390f35b61006a610097565b005b60015461007f906001600160a01b031681565b6040516001600160a01b039091168152602001610059565b6000544210156100e75760405162461bcd60e51b8152602060048201526016602482015275165bdd4818d85b89dd081dda5d1a191c985dc81e595d60521b60448201526064015b60405180910390fd5b6001546001600160a01b031633146101385760405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932b713ba103a34329037bbb732b960611b60448201526064016100de565b604080514781524260208201527fbf2ed60bd5b5965d685680c01195c9514e4382e28e3a5a2d2d5244bf59411b93910160405180910390a16001546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156101a9573d6000803e3d6000fd5b5056fea264697066735822122076fbe7b8ebb7b119ae24cf4af4db6766738a27ad6a012e06535e6d12512b58ae64736f6c63430008120033

foundry bytecode:

0x60806040526040516102a53803806102a58339810160408190526100229161009b565b8042106100815760405162461bcd60e51b815260206004820152602360248201527f556e6c6f636b2074696d652073686f756c6420626520696e207468652066757460448201526275726560e81b606482015260840160405180910390fd5b600055600180546001600160a01b031916331790556100b4565b6000602082840312156100ad57600080fd5b5051919050565b6101e2806100c36000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063251c1aa3146100465780633ccfd60b146100625780638da5cb5b1461006c575b600080fd5b61004f60005481565b6040519081526020015b60405180910390f35b61006a610097565b005b60015461007f906001600160a01b031681565b6040516001600160a01b039091168152602001610059565b6000544210156100e75760405162461bcd60e51b8152602060048201526016602482015275165bdd4818d85b89dd081dda5d1a191c985dc81e595d60521b60448201526064015b60405180910390fd5b6001546001600160a01b031633146101385760405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932b713ba103a34329037bbb732b960611b60448201526064016100de565b604080514781524260208201527fbf2ed60bd5b5965d685680c01195c9514e4382e28e3a5a2d2d5244bf59411b93910160405180910390a16001546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156101a9573d6000803e3d6000fd5b5056fea26469706673582212209b8b2d501f0fe8324516d05e10e2dfc5f7400b4d4d69cc308f6a3a5a8779cf6164736f6c63430008120033

Compare:
image

@mds1
Copy link
Collaborator

mds1 commented Aug 10, 2023

These are different metadata hashes. The trailing 0033 is the length of the metadata hash (51 btyes) and it starts at the a264 bytes (in the most recent screenshot, second row from the bottom, near the beginning of the row). See the solidity docs for more info.

If that's the only difference the actual executable code is identical and this difference is expected. The metadata hash is a function of various things, including filepaths, so if foundry and hardhat handle e.g. remappings differently you'll get a different hash.

Note that both foundry and hardhat provide options to turns off this bytecode hash if you'd like to remove the discrepancy.

Going to close this since this is solved, but feel free to ask any more questions :)

@mds1 mds1 closed this as completed Aug 10, 2023
@github-project-automation github-project-automation bot moved this from Todo to Done in Foundry Aug 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug
Projects
Archived in project
Development

No branches or pull requests

3 participants