diff --git a/packages/lib-sourcify/src/lib/verification.ts b/packages/lib-sourcify/src/lib/verification.ts index aa126c49a..7e6ac8175 100644 --- a/packages/lib-sourcify/src/lib/verification.ts +++ b/packages/lib-sourcify/src/lib/verification.ts @@ -364,6 +364,11 @@ export async function matchWithCreationTx( creatorTxHash: string, recompiledMetadata: Metadata ) { + if (recompiledCreationBytecode === '0x') { + match.status = null; + match.message = `Failed to match with creation bytecode: recompiled contract's creation bytecode is empty`; + return; + } const creatorTx = await getTx(creatorTxHash, sourcifyChain); const creatorTxData = creatorTx.input; diff --git a/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json new file mode 100644 index 000000000..d434360de --- /dev/null +++ b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/metadata.json @@ -0,0 +1,44 @@ +{ + "compiler": { + "version": "0.6.12+commit.27d51765" + }, + "language": "Solidity", + "output": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "compilationTarget": { + "sources/FFF.sol": "FFF" + }, + "evmVersion": "istanbul", + "libraries": {}, + "metadata": { + "bytecodeHash": "ipfs" + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "sources/FFF.sol": { + "keccak256": "0x7ed3554b3f768ad3b3069d7fc8b1a08a24500507fc8a60eb11c726e37f3cd9a3", + "urls": [ + "bzz-raw://6d83c127e075a149ec14c6af579bc7b24955cdb7578ae7da2f253b7142d267cc", + "dweb:/ipfs/QmW6tdCTV7X5dd5LCKDWedbMmkurQTMi4ePx7LY3DNuLn7" + ] + } + }, + "version": 1 +} diff --git a/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol new file mode 100644 index 000000000..b12b1d274 --- /dev/null +++ b/packages/lib-sourcify/test/sources/AbstractCreationBytecodeAttack/sources/FFF.sol @@ -0,0 +1,6 @@ +pragma solidity 0.6.12; + +abstract contract FFF{ + constructor (uint256 a) public payable { + } +} \ No newline at end of file diff --git a/packages/lib-sourcify/test/verification.spec.ts b/packages/lib-sourcify/test/verification.spec.ts index 248feb2f5..821bed1bf 100644 --- a/packages/lib-sourcify/test/verification.spec.ts +++ b/packages/lib-sourcify/test/verification.spec.ts @@ -623,6 +623,47 @@ describe('lib-sourcify tests', () => { expectMatch(match, null, deployedAddress, undefined); // status is null }); + it('should fail to matchWithCreationTx when passing an abstract contract', async () => { + const contractFolderPath = path.join( + __dirname, + 'sources', + 'WithImmutables' + ); + + const [deployedAddress, creatorTxHash] = await deployFromAbiAndBytecode( + localWeb3Provider, + contractFolderPath, + accounts[0], + ['12345'] + ); + + const maliciousContractFolderPath = path.join( + __dirname, + 'sources', + 'AbstractCreationBytecodeAttack' + ); + const checkedContracts = await checkFilesFromContractFolder( + maliciousContractFolderPath + ); + const recompiled = await checkedContracts[0].recompile(); + const match = { + address: deployedAddress, + chainId: sourcifyChainGanache.chainId.toString(), + status: null, + }; + const recompiledMetadata: Metadata = JSON.parse(recompiled.metadata); + + await matchWithCreationTx( + match, + recompiled.creationBytecode, + sourcifyChainGanache, + deployedAddress, + creatorTxHash, + recompiledMetadata + ); + expectMatch(match, null, deployedAddress, undefined); // status is null + }); + it('should successfuly verify with matchWithCreationTx with creationTxHash', async () => { const contractFolderPath = path.join( __dirname,