Skip to content

Commit

Permalink
Fix-unoptimized-ir-mismatch (#1140)
Browse files Browse the repository at this point in the history
Fixes #1088
  • Loading branch information
kuzdogan authored Aug 14, 2023
2 parents a684be0 + 1dd63e4 commit 8f0c073
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 10 deletions.
10 changes: 8 additions & 2 deletions packages/lib-sourcify/src/lib/CheckedContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,20 @@ export class CheckedContract {
return null;
}

public async recompile(): Promise<RecompilationResult> {
public async recompile(
forceEmscripten = false
): Promise<RecompilationResult> {
if (!CheckedContract.isValid(this)) {
await CheckedContract.fetchMissing(this);
}

const version = this.metadata.compiler.version;

const output = await useCompiler(version, this.solcJsonInput);
const output = await useCompiler(
version,
this.solcJsonInput,
forceEmscripten
);
if (
!output.contracts ||
!output.contracts[this.compiledPath] ||
Expand Down
2 changes: 1 addition & 1 deletion packages/lib-sourcify/src/lib/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface ILogger {

// Default logger behavior
export const DefaultLogger: ILogger = {
logLevel: 2,
logLevel: process.env.NODE_ENV === 'production' ? 2 : 4,
setLevel(level: number) {
this.logLevel = level;
},
Expand Down
10 changes: 7 additions & 3 deletions packages/lib-sourcify/src/lib/solidityCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ export function findSolcPlatform(): string | false {
* @returns stringified solc output
*/

export async function useCompiler(version: string, solcJsonInput: JsonInput) {
export async function useCompiler(
version: string,
solcJsonInput: JsonInput,
forceEmscripten = false
): Promise<any> {
// For nightly builds, Solidity version is saved as 0.8.17-ci.2022.8.9+commit.6b60524c instead of 0.8.17-nightly.2022.8.9+commit.6b60524c.
// Not possible to retrieve compilers with "-ci.".
if (version.includes('-ci.')) version = version.replace('-ci.', '-nightly.');
Expand All @@ -45,11 +49,11 @@ export async function useCompiler(version: string, solcJsonInput: JsonInput) {

const solcPlatform = findSolcPlatform();
let solcPath;
if (solcPlatform) {
if (solcPlatform && !forceEmscripten) {
solcPath = await getSolcExecutable(solcPlatform, version);
}
let startCompilation: number;
if (solcPath) {
if (solcPath && !forceEmscripten) {
logDebug(`Compiling with solc binary ${version} at ${solcPath}`);
startCompilation = Date.now();
try {
Expand Down
1 change: 1 addition & 0 deletions packages/lib-sourcify/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export interface Metadata {
enabled: boolean;
runs: number;
};
viaIR?: boolean;
outputSelection?: any;
};
sources: MetadataSources;
Expand Down
26 changes: 24 additions & 2 deletions packages/lib-sourcify/src/lib/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import { defaultAbiCoder as abiCoder, ParamType } from '@ethersproject/abi';
import { AbiConstructor } from 'abitype';
import { logInfo } from './logger';
import SourcifyChain from './SourcifyChain';
import { lt } from 'semver';

export async function verifyDeployed(
checkedContract: CheckedContract,
sourcifyChain: SourcifyChain,
address: string,
/* _contextVariables?: ContextVariables, */
creatorTxHash?: string
creatorTxHash?: string,
forceEmscripten = false
): Promise<Match> {
const match: Match = {
address,
Expand All @@ -46,7 +48,7 @@ export async function verifyDeployed(
checkedContract.name
} at address ${address} on chain ${sourcifyChain.chainId.toString()}`
);
const recompiled = await checkedContract.recompile();
const recompiled = await checkedContract.recompile(forceEmscripten);

if (
recompiled.deployedBytecode === '0x' ||
Expand Down Expand Up @@ -176,6 +178,26 @@ export async function verifyDeployed(
}
}

// Handle when <0.8.21 and with viaIR and with optimizer disabled https://github.com/ethereum/sourcify/issues/1088
if (
lt(checkedContract.metadata.compiler.version, '0.8.21') &&
!checkedContract.metadata.settings.optimizer?.enabled &&
checkedContract.metadata.settings?.viaIR
) {
logInfo(
`Forcing compiling with the Emscripten compiler to match the deployed bytecode for ${
checkedContract.name
} to verify at ${address} on chain ${sourcifyChain.chainId.toString()}`
);
return verifyDeployed(
checkedContract,
sourcifyChain,
address,
creatorTxHash,
true // Force compiling with Emscripten compiler
);
}

throw Error("The deployed and recompiled bytecode don't match.");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"abi": [],
"bytecode": "0x608060405234156100135761001261003a565b5b61001b61003e565b610023610031565b61033a610041823961033a81f35b5f604051905090565b5f80fd5b56fe60806040526004361061002e576100165f3561003b565b80639942ec6f810361002b5761002a61007a565b5b50505b6100366100b3565b610303565b5f8160e01c9050919050565b5f604051905090565b5f80fd5b5f80fd5b5f818303121561006b5761006a610054565b5b5050565b5f8082019050919050565b341561008957610088610050565b5b610094366004610058565b61009c6102c1565b6100a4610047565b6100ad8161006f565b81810382f35b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6100fd826100b7565b810181811067ffffffffffffffff8211171561011c5761011b6100c7565b5b80604052505050565b5f61012e610047565b905061013a82826100f4565b919050565b5f67ffffffffffffffff821115610159576101586100c7565b5b602082029050919050565b5f61016e8261013f565b61017781610125565b915050919050565b813682375050565b5f61019182610164565b90508061019d8361013f565b6101a7818361017f565b5050919050565b5f6101b96002610187565b905090565b5f819050919050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b5f8160f81b9050919050565b5f61021861021361020e846101be565b6101f2565b6101c7565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60029050919050565b5f6102608261024c565b831061026f5761026e61021f565b5b6020830280830191505092915050565b5f819050919050565b5f819050919050565b5f6102ab6102a66102a1846101be565b610288565b61027f565b9050919050565b6102bb826101c7565b81525050565b60025f6102cc6101ae565b8091505f6102d9816101fe565b83805f836102f8816102f36102ed85610291565b86610256565b6102b2565b505050505050505050565bfea26469706673582212206456eef5862511a5a1c1409b7dcd1a578223a0ff02c5a9106a33156d21837cf964736f6c63430008140033"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"compiler":{"version":"0.8.20+commit.a1b79de6"},"language":"Solidity","output":{"abi":[{"inputs":[],"name":"f2","outputs":[],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"A":"C"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[],"viaIR":true},"sources":{"A":{"keccak256":"0xd679cd539599ca78bc3821e0db8a70e100f0b7f7dcdb3c99b428c49a1d6ebe69","urls":["bzz-raw://36a9f5a039c61d73850e994d18cf204b6c292f415cfe6c69962f9aeb2078de05","dweb:/ipfs/QmXTHUdb47N3kh41uEVYvinz19oH4n8CKVhwduWviyJF7T"]}},"version":1}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
contract C {
function f2() public {
bytes1[2] memory k;
k[0] = bytes1(0);
}
}
5 changes: 3 additions & 2 deletions packages/lib-sourcify/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ import { expect } from 'chai';
import { ContractFactory, Signer } from 'ethers';
/**
* Function to deploy contracts from provider unlocked accounts
* contractFolderPath must contain an artifact.json file with "abi" and "bytecode" fields
*
* @returns the address of the deployed contract and the creator tx hash
*/
// TODO: ABI type definition
export async function deployFromAbiAndBytecode(
signer: Signer,
contractFolderPath: string,
args?: any[]
constructorArgs?: any[]
) {
const artifact = require(path.join(contractFolderPath, 'artifact.json'));
// Deploy contract
Expand All @@ -35,7 +36,7 @@ export async function deployFromAbiAndBytecode(
artifact.bytecode,
signer
);
const deployment = await contractFactory.deploy(...(args || []));
const deployment = await contractFactory.deploy(...(constructorArgs || []));
await deployment.waitForDeployment();

const contractAddress = await deployment.getAddress();
Expand Down
29 changes: 29 additions & 0 deletions packages/lib-sourcify/test/verification.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { expect } from 'chai';
import {
SourcifyChain,
calculateCreate2Address,
findSolcPlatform,
/*
getBytecode,
matchWithSimulation,
Expand Down Expand Up @@ -426,6 +427,34 @@ describe('lib-sourcify tests', () => {
);
expectMatch(match, 'perfect', contractAddress);
});

// https://github.com/ethereum/sourcify/issues/1088
it('should compile again with a different platform binary and verify for contracts --viaIR and optimizer disabled <=v0.8.20', async function () {
const contractFolderPath = path.join(
__dirname,
'sources',
'ViaIRUnoptimizedMismatch'
);
const solcPlatform = findSolcPlatform();
// can't really run this if we can't run a platform-native binary but only Emscripten (solc-js)
if (!solcPlatform) {
console.log(
`skipping test as the running machine can't run a platform-native binary. The platform and architechture is ${process.platform} ${process.arch}`
);
this.skip();
}
// The artifact has the bytecode from the Emscripten compiler.
const { contractAddress } = await deployFromAbiAndBytecode(
signer,
contractFolderPath
);
const match = await checkAndVerifyDeployed(
contractFolderPath,
sourcifyChainGanache,
contractAddress
);
expectMatch(match, 'perfect', contractAddress);
});
});

describe('Unit tests', function () {
Expand Down

0 comments on commit 8f0c073

Please sign in to comment.