foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.29k stars 1.75k forks source link

bug(`forge verify-contract`): Unable to verify on explorer or sourcify while flattening works #8470

Open duncancmt opened 3 months ago

duncancmt commented 3 months ago

Component

Forge

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

What version of Foundry are you on?

forge 0.2.0 (f625d0f 2024-04-02T00:15:52.692780824Z)

What command(s) is the bug in?

forge verify-contract

Operating System

Linux

Describe the bug

TL;DR: OptimismSettler and ArbitrumSettler from https://github.com/0xProject/0x-settler/commit/ecd28b3379856cd38d936dc40ddc66d1e2a7957a won't verify on their respective explorers or on Sourcify.

I apologize that I don't have a more minimal repro. I tried comparing successfully-verified contracts (e.g. LineaSettler) against the unsuccessfully-verified contracts and can't find anything that stands out.

I can't for the life of me get this contract to verify and I'm really at a loss about what specifically it is that's stopping it from being verified. I would workaround with forge flatten, but since the fix for #7554 hasn't landed yet, I can't try that. I'm reporting this as a bug due to 2 interesting observations:

I put an older version of forge above, but I can also replicate this with forge 0.2.0 (f625d0f 2024-04-02T00:15:52.692780824Z). The version above is the one that I've pinned due to previous issues with contract verification, but now I've run in to an issue that I can't workaround.

cd .../0x-settler
git checkout ecd28b3 # presently `master`
declare -r etherscan_key='YOUR_API_KEY_HERE'
declare -r rpc_url='YOUR_RPC_HERE'
declare -r git_commit="$(git rev-parse HEAD)" # ecd28b3379856cd38d936dc40ddc66d1e2a7957a
declare -r constructor_args="$(cast abi-encode 'constructor(bytes20)' "$git_commit")" # 0xecd28b3379856cd38d936dc40ddc66d1e2a7957a000000000000000000000000
declare -r registry='0x00000000000004533Fe15556B1E086BB1A72cEae'
declare -r deployed_address="$(cast call --rpc-url "$rpc_url" --chain 10 "$registry" 'ownerOf(uint256)(address)' 2)" # 0x868c6C9e424801fEe351000fB9B8DE756fa97c6d
forge verify-contract --watch --chain 10 --etherscan-api-key "$etherscan_key" --verifier-url 'https://api-optimistic.etherscan.io/api' --constructor-args "$constructor_args" "$deployed_address" OptimismSettler
forge verify-contract --watch --chain 10 --verifier sourcify --constructor-args "$constructor_args" "$deployed_address" OptimismSettler

If you try this again with Arbitrum instead of Optimism, Arbiscan outright refuses verification because it doesn't like the Cancun hardfork. Sourcify still fails with a similar error message.

The other contract that is compiled from the same source file is OptimismSettlerMetaTxn (ArbitrumSettlerMetaTxn) and its deployed address can be found by querying the same registry contract but with tokenId 3 instead of 2. (0x4DA7632F394F574576255A59b026841a700F0617 on Optimism)

Thanks a lot for taking a look!

zerosnacks commented 3 months ago

Hi @duncancmt, would you mind retrying it with forge flatten since #7554 has now landed?

I can confirm that the generated deployedBytecode generated by Foundry is the exact same as https://optimistic.etherscan.io/address/0x868c6C9e424801fEe351000fB9B8DE756fa97c6d and the error is: Details: Fail - Unable to verify. Compiled contract deployment bytecode does NOT match the transaction deployment bytecode.

Sourcify fails with a compiler build error complaining that files are not found.

Considering the contract was dynamically created in the constructor it may be a bug in Etherscan, see related: https://github.com/foundry-rs/foundry/issues/6023

duncancmt commented 3 months ago

would you mind retrying it with forge flatten since #7554 has now landed?

I'll give that a shot with our next deployment. Should be later this week.

Considering the contract was dynamically created in the constructor

Ahh, it's actually not deployed from the constructor of another contract. It's a bit convoluted (you can see the exact mechanism in Create3.sol), but the trace looks like

Deployer Proxy (delegatecall) -> Deployer Impl
    Deployer Impl (create2) -> Create3 Shim
    Deployer Impl (call) -> Create3 Shim
        Create3 Shim (create) -> OptimismSettler
    Deployer Impl (call) -> Create3 Shim
        Create3 Shim (selfdestruct)

so I don't think that #6023 is directly applicable. Especially since it would be odd for Etherscan and Sourcify to have the same issue, but not complain about a different contract deployed in the same way from the same source file.

duncancmt commented 3 months ago

would you mind retrying it with forge flatten since #7554 has now landed?

I'll give that a shot with our next deployment. Should be later this week.

We did a deployment using flattened source to 0x1a3b48EA0C6e9A52511A196A287fa8371e5Ee7a0 and 0x607798c55Fb37e842b8fa92a148cd51dBA8BB22F on Optimism. It worked fine. I'm not sure where that puts us with this issue. Obviously I can continue to use flattened source to workaround this issue, but the actual underlying problem isn't addressed

zerosnacks commented 2 weeks ago

Hi @duncancmt

There have been quite a few improvements to the verification flow recently, would you mind attempting to reproduce this, perhaps on a next deployment? I would like to rule out issues on the explorers side and see if this is still an active issue.

Thanks!