Summary
I came across a contract that could not be verified on Sourcify because the Sourcify's compilation output bytecode is different than the author's (Hardhat). Diving deeper I've found out the difference comes to the surface when some other contracts that are unrelated to the compilation target are added to compilation.
Specifically these two standard JSON inputs yield different bytecode for the same contract CompoundLens.sol:
CompoundLens-solc-input-Sourcify-bytecode.json.txt
CompoundLens-solc-input-Hardhat-bytecode.json.txt
The only input sources differences are the following which are unrelated to CompoundLens:
[
'@openzeppelin/contracts/interfaces/draft-IERC1822.sol',
'@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol',
'@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol',
'@openzeppelin/contracts/proxy/Proxy.sol',
'@openzeppelin/contracts/proxy/beacon/IBeacon.sol',
'@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol',
'@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol',
'@openzeppelin/contracts/utils/StorageSlot.sol'
]
You'll notice the bytecodes differ even when the metadata hashes are the same. This is unexpected as the different sources listed above are not related to CompoundLens. CompoundLens already compiles without those contracts are input in CompoundLens-solc-input-Sourcify-bytecode.json but when added in CompoundLens-solc-input-Hardhat-bytecode.json the contract's bytecode changes.
To reproduce
Using Solidity version v0.8.19
Output the bytecodes
- Sourcify
cat CompoundLens-solc-input-Sourcify-bytecode.json.txt | solc --standard-json | jq '.contracts."contracts/Comptroller/CompoundLens.sol".CompoundLens.evm.bytecode.object' > CompoundLens-Sourcify-creation-bytecode.txt
- Hardhat
cat CompoundLens-solc-input-Hardhat-bytecode.json.txt | solc --standard-json | jq '.contracts."contracts/Comptroller/CompoundLens.sol".CompoundLens.evm.bytecode.object' > CompoundLens-Hardhat-creation-bytecode.txt
Compare the bytecodes:
git diff --word-diff --word-diff-regex=. CompoundLens-Sourcify-creation-bytecode.txt CompoundLens-Hardhat-creation-bytecode.txt
Background
The contracts are on this Github repo (verify branch): https://github.com/meterio/sumer-project/tree/verify
To compile (and deploy) the original sources:
git clone https://github.com/meterio/sumer-project/
cd sumer-project
rm -rf dist
yarn
yarn compile
npx hardhat dcl --rpc http://rpctest.meter.io/ --pk $PRIV_KEY
The contract is also deployed at: https://goerli.etherscan.io/address/0x46df081108b2e2FDf1bF1E84Eeb2D7ec3AdA0061
The bytecode diff between the Sourcify output and Hardhat output was not in the metadata hash or in a certain recognizable pattern for me:

CompoundLens-hardhat-recompiled-creation.txt
CompoundLens-recompiled-creation.txt
To generate the diff: git diff --word-diff --word-diff-regex=. CompoundLens-hardhat-recompiled-creation.txt CompoundLens-recompiled-creation.txt
What I tried to do was to start from the standard JSON input of Sourcify and try to reach the Hardhat output bytecode in iterations:
initial Sourcify JSON input: CompoundLens-solc-input.json.txt
Hardhat JSON input: CompoundLens-hardhat-solc-input.json.txt
- Tried using the full compilation settings from Hardhat.
Using the same settings in Hardhat in the initial Sourcify input didn't change the bytecode.
- Tried using the whole
sources from the Harhat input in the initial Sourcify input
Yes by using all of the sources from Hardhat, one generates the Hardhat's bytecode output.
Next, I iteratively copied sources from the Hardhat input to the Sourcify input to see adding which sources cause the change in the bytecode.
Sourcify's initial standard JSON input:

Hardhat's standard JSON input (clipped):

On each step I copied a contract that might be a potential cause of change, resolved the dependencies by also adding them, compiled the new iterated JSON input and compared the bytecodes.
Finally, I found a minimal standard JSON diff, that adding the specific sources would change the bytecode output. These are laid out in the above Summary section.
Environment
- Compiler version:
v0.8.19
- Target EVM version (as per compiler settings): paris
- Framework/IDE (e.g. Truffle or Remix): Hardhat and solc CLI
- EVM execution environment / backend / blockchain client:
- Operating system: MacOS
Summary
I came across a contract that could not be verified on Sourcify because the Sourcify's compilation output bytecode is different than the author's (Hardhat). Diving deeper I've found out the difference comes to the surface when some other contracts that are unrelated to the compilation target are added to compilation.
Specifically these two standard JSON inputs yield different bytecode for the same contract
CompoundLens.sol:CompoundLens-solc-input-Sourcify-bytecode.json.txt
CompoundLens-solc-input-Hardhat-bytecode.json.txt
The only input sources differences are the following which are unrelated to
CompoundLens:You'll notice the bytecodes differ even when the metadata hashes are the same. This is unexpected as the different sources listed above are not related to
CompoundLens.CompoundLensalready compiles without those contracts are input inCompoundLens-solc-input-Sourcify-bytecode.jsonbut when added inCompoundLens-solc-input-Hardhat-bytecode.jsonthe contract's bytecode changes.To reproduce
Using Solidity version
v0.8.19Output the bytecodes
Compare the bytecodes:
Background
The contracts are on this Github repo (
verifybranch): https://github.com/meterio/sumer-project/tree/verifyTo compile (and deploy) the original sources:
The contract is also deployed at: https://goerli.etherscan.io/address/0x46df081108b2e2FDf1bF1E84Eeb2D7ec3AdA0061
The bytecode diff between the Sourcify output and Hardhat output was not in the metadata hash or in a certain recognizable pattern for me:

CompoundLens-hardhat-recompiled-creation.txt
CompoundLens-recompiled-creation.txt
To generate the diff:
git diff --word-diff --word-diff-regex=. CompoundLens-hardhat-recompiled-creation.txt CompoundLens-recompiled-creation.txtWhat I tried to do was to start from the standard JSON input of Sourcify and try to reach the Hardhat output bytecode in iterations:
initial Sourcify JSON input: CompoundLens-solc-input.json.txt
Hardhat JSON input: CompoundLens-hardhat-solc-input.json.txt
Using the same settings in Hardhat in the initial Sourcify input didn't change the bytecode.
sourcesfrom the Harhat input in the initial Sourcify inputYes by using all of the sources from Hardhat, one generates the Hardhat's bytecode output.
Next, I iteratively copied sources from the Hardhat input to the Sourcify input to see adding which sources cause the change in the bytecode.
Sourcify's initial standard JSON input:

Hardhat's standard JSON input (clipped):

On each step I copied a contract that might be a potential cause of change, resolved the dependencies by also adding them, compiled the new iterated JSON input and compared the bytecodes.
Finally, I found a minimal standard JSON diff, that adding the specific sources would change the bytecode output. These are laid out in the above Summary section.
Environment
v0.8.19