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

Verify contracts using Solc standard JSON input #416

Merged

Conversation

canepat
Copy link
Contributor

@canepat canepat commented Jan 2, 2020

This PR introduces the contract source verification on Etherscan using the Solc standard JSON input as proposed in issue #414.

Fixes #414

Working Assumptions
I've made the following working assumptions:

  • a new test project contracts-nameclash-project is added to prove the name clash using flattening
  • the verify-contract task now uses the Solc standard JSON input (instead of the Solidity single-file provided by flattening) as code format with Etherscan API
  • the buidler-etherscan test project is extended with contracts producing some name clash
  • the Solc standard JSON input is currently saved in config.paths.artifacts folder
  • the Solc version for the buidler-etherscan test project is upgraded to 0.5.15 because using version 0.5.1 I was unable to verify on Etherscan the existent TestContract1, just upgrading Solc makes it work

Limitations
Currently there are some limitations:

  • the Solc standard JSON input is saved always in config.paths.artifacts folder, no customization is possible
  • when using the Solc standard JSON input the Etherscan API spec requires that the contractName parameter is provided in the <path_to_sol>:<contract_name> format. Currently it is hard-coded as contracts/${taskArgs.contractName}.sol:${taskArgs.contractName} in buidler-etherscan: far from ideal but making it work for any contract would require to change the verify-contract task arguments, so I prefer to leave this for a next PR, if this one is accepted

I'm looking forward to hear if this PR sounds good and in case to receive any advice or suggestion for improving this solution

canepat added 4 commits January 1, 2020 22:39
Fix some errors in plugin tests
Use Solc version 0.5.15 to obtain source verification on Etherscan
Add contracts with name clash in test project
Add test to check source verification using contracts with name clash
Save the Solc standard JSON input before compiling
Load the Solc standard JSON input for verifying
Change the Etherscan API parameters to use the Solc standard JSON input
Improve integration test descriptions
@alcuadrado
Copy link
Member

Hey @canepat,

Thanks for making this PR. I'm sorry I couldn't review it earlier.

I'm a little confused about how this works, as my understanding is that etherscan's API only accepts flattened sources and not the standard json input.

@alcuadrado
Copy link
Member

Ohhhh, they just reuse some param names, but support the standard json format now! This is great news! 🥳

I'll look deeper into this later, but looking really good so far.

Much appreciated!

Remove unuseful custom load and save for Solc input
@canepat
Copy link
Contributor Author

canepat commented Feb 6, 2020

I've just added the usage of await bre.run(TASK_COMPILE_GET_COMPILER_INPUT) removing the unnecessary custom functions for loading/saving the standard Solc JSON input.

The last commit passes in Travis CI but fails in Netlify for some reason I don't understand, if you have any clue it would be great.

@alcuadrado
Copy link
Member

Thanks @canepat!

I cleared netlifies cache, re-run it, and not it works.

I'll review your changes tomorrow.

const request = toRequest({
apiKey: etherscan.apiKey,
contractAddress: taskArgs.address,
sourceCode: source,
contractName: taskArgs.contractName,
contractName: `contracts/${taskArgs.contractName}.sol:${taskArgs.contractName}`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is the only problematic thing I can see, as it imposes the same names for files and contracts.

This could be fixed by doing something like

const solcInput : SolcInput = JSON.stringify(await run(TASK_COMPILE_GET_COMPILER_INPUT)); 

const filesWithContract = Object.entries(solcInput.sources).find((fileGlobalName, {content}) => hasContractDeclaration(content, taskArgs.contractName)).map((globalName) => globalName);

if (filesWithContract.length === 0) {
   // contract not found
   throw BuidlerPluginError(...);
}

if (filesWithContract.length > 1) {
   // throw error? what should be done here??
}

const contractName = `${filesWithContract[0}:${taskArgs.contractName}`;

Copy link
Contributor Author

@canepat canepat Feb 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're absolutely right, it's a limitation of this PR.

An idea for handling any use case is extending the verify-contract task arguments to accept an optional contractFilePath argument (e.g. contracts/A.sol) to build the complete contract name as ${taskArgs.contractFilePath}:${taskArgs.contractName}; when the contractFilePath is not given, the default simplified name contracts/${taskArgs.contractName}.sol:${taskArgs.contractName} will be used.

Another option could be changing the contractName argument of the verify-contract task to become the full contract name, specified exactly as expected by Etherscan API ${contractFilePath}:${contractName} (e.g. contracts/A.sol:B.sol).

IMHO the latter option is slightly preferable even if it changes a bit the semantic of the contractName argument of the verify-contract task.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alcuadrado Does this issue gate merging? Thanks!

Copy link
Contributor Author

@canepat canepat Feb 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pcowgill this issue has been resolved in last commit 3695e1c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@canepat Great, thanks. I thought so but I wanted to confirm that

@pcowgill
Copy link
Contributor

@alcuadrado Whenever you have time, there’s another commit here for your review. Thanks!

@alcuadrado
Copy link
Member

Hey @canepat and @pcowgill, we were a little busy preparing this new release. Now that it's out, I'll review this soon.

Can you update it and change the base branch to development? Thanks!

@canepat canepat changed the base branch from master to development February 27, 2020 23:41
@canepat
Copy link
Contributor Author

canepat commented Feb 28, 2020

I've just merged from and changed the base branch to development.

@pcowgill
Copy link
Contributor

@tmilar @fvictorio Might either of you have a chance to review this PR this week or next? Thanks!

@alcuadrado alcuadrado merged commit 28ba5ba into NomicFoundation:development Apr 1, 2020
@alcuadrado
Copy link
Member

Thanks for creating this PR @canepat, and thanks for your patience!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Contract verification fails when flattened source contains contracts with the same name
3 participants