diff --git a/docs/dapp/images/tools/sourcify1.png b/docs/dapp/images/tools/sourcify1.png new file mode 100644 index 0000000000..b6dba793af Binary files /dev/null and b/docs/dapp/images/tools/sourcify1.png differ diff --git a/docs/dapp/images/tools/sourcify2.png b/docs/dapp/images/tools/sourcify2.png new file mode 100644 index 0000000000..42b201dfe2 Binary files /dev/null and b/docs/dapp/images/tools/sourcify2.png differ diff --git a/docs/dapp/images/tools/sourcify3.png b/docs/dapp/images/tools/sourcify3.png new file mode 100644 index 0000000000..ac32713f68 Binary files /dev/null and b/docs/dapp/images/tools/sourcify3.png differ diff --git a/docs/dapp/tools/README.mdx b/docs/dapp/tools/README.mdx index 4c5596ded3..ffb1be2e34 100644 --- a/docs/dapp/tools/README.mdx +++ b/docs/dapp/tools/README.mdx @@ -9,8 +9,8 @@ developers using [Remix] (*unencrypted transactions only*), [Sourcify], [Discord][discord] if you are using a tool that has problems integrating with Oasis. -[Remix]: remix.md -[Sourcify]: /dapp/sapphire/verification +[Remix]: ./remix.md +[Sourcify]: ./verification.md [localnet]: ./localnet.mdx [Band]: ./band.md [discord]: https://oasis.io/discord @@ -18,9 +18,9 @@ Oasis. ## See also diff --git a/docs/dapp/tools/abi-playground.md b/docs/dapp/tools/abi-playground.md index 8150f3d0f7..4c1919b197 100644 --- a/docs/dapp/tools/abi-playground.md +++ b/docs/dapp/tools/abi-playground.md @@ -82,6 +82,6 @@ Should you have any other problems or questions, do not hesitate to share them w [abi-playground]: https://abi-playground.oasis.io/ [Explorer]: https://explorer.oasis.io/ -[localnet]: /dapp/tools/localnet -[verification]: /dapp/sapphire/verification +[localnet]: ./localnet.mdx +[verification]: ./verification.md [discord]: https://oasis.io/discord diff --git a/docs/dapp/tools/verification.md b/docs/dapp/tools/verification.md new file mode 100644 index 0000000000..79acf902f7 --- /dev/null +++ b/docs/dapp/tools/verification.md @@ -0,0 +1,143 @@ +--- +description: Verifying deployed contracts +--- + +# Contract Verification + +[Sourcify] is the preferred service for the [verification of smart +contracts][ethereum-contract-verify] deployed on Sapphire. Make sure you have +the **address of each deployed contract** available (your deployment scripts +should report those) and the **contracts JSON metadata file** generated when +compiling contracts (Hardhat stores it inside the `artifacts/build-info` folder +and names it as a 32-digit hex number). If your project contains multiple +contracts, you will need to verify each contract separately. + +:::warning Contract deployment encryption + +**Do not deploy your contract with an encrypted contract deployment transaction, +if you want to verify it.** For example, if your `hardhat.config.ts` +or deployment script contains `import '@oasisprotocol/sapphire-hardhat'` or +`import '@oasisprotocol/sapphire-paratime'` lines at the beginning, you should +comment those out for the deployment. + +Verification services will try to match the contract deployment transaction code +with the one in the provided contract's metadata. Because the transaction was +encrypted with an ephemeral ParaTime key, the verification service will not be +able to decrypt it. Some services may extract the contract's bytecode from the +chain directly by calling `eth_getCode` RPC, but this will not work correctly +for contracts with immutable variables. + +::: + +## Verification with Hardhat + +If you use Hardhat to deploy your contracts, consider using the +[hardhat-verify] plugin. + +To configure it, add the following to your `hardhat.config.ts` file: + +```js title="hardhat.config.ts" + etherscan: { + // Enabled by default (not supported on Sapphire) + enabled: false + }, + sourcify: { + // Disabled by default + // Doesn't need an API key + enabled: true + } +``` + +Now you can use the `verify` task: + +```shell +pnpm hardhat verify --network sapphire-testnet DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1" +``` + +[hardhat-verify]: https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify + +## Verification with Foundry + +[Foundry] natively supports Sourcify verification. To use **Sourcify** as a +provider, specify it with the `--verifier` option. + +Example: + +```shell +forge verify-contract
src/MyToken.sol:MyToken --verifier sourcify +``` + +:::info +To see all available options and more examples visit the +**[verify-contract page of foundry][foundry-verify]** or the **[sourcify docs]** +::: + +[Foundry]: https://book.getfoundry.sh +[foundry-verify]: https://book.getfoundry.sh/reference/forge/forge-verify-contract +[sourcify docs]: https://docs.sourcify.dev/docs/how-to-verify/#foundry + +## Verification on Sourcify + +To verify maunally a contract deployed on Sapphire Mainnet or Testnet on Sourcify: + +1. Visit the [Sourcify] website and hit the "VERIFY CONTRACT" button. + + ![Sourcify website](../images/tools/sourcify1.png) + +2. Upload the contracts JSON metadata file. (Sourcify can parse the Hardhat + .json output file under `artifacts/build-info`) + + ![Sourcify: Upload metadata JSON file](../images/tools//sourcify2.png) + + :::tip Store your metadata files + + For production deployments, it is generally a good idea to **archive your + contract metadata JSON file** since it is not only useful for the + verification, but contains a copy of all the source files, produced bytecode, + an ABI, compiler and other relevant contract-related settings that may be + useful in the future. Sourcify will store the metadata file for you and will + even make it available via IPFS, but it is still a good idea to store it + yourself. + + ::: + +3. Sourcify will decode the metadata and prepare a list of included contracts on + the right. Enter the address of the specific contract and select the "Oasis + Sapphire" or "Oasis Sapphire Testnet" chain for Mainnet or Testnet + accordingly. If your contract assigns any immutable variables in the + constructor, you will also need to correctly fill those out under the "More + Inputs (optional)" panel. Finally, click on the "Verify" button. + + ![Sourcify: Verify contract](../images/tools/sourcify3.png) + +4. If everything goes well, you will get a *Perfect match* notice. Your + contract is now verified. Congratulations! + +In case of a *Partial match*, the contracts metadata JSON differs from the one +used for deployment although the compiled contract bytecode matched. Make sure +the source code `.sol` file of the contract is the same as the one used during the +deployment (including the comments, variable names and source code file +names) and use the same version of Hardhat and solc compiler. + +:::info +You can also explore all verification methods on Sourcify by reading the +[official Sourcify contract verification instructions][sourcify-contract-verify]. +::: + +[Sourcify]: https://sourcify.dev/ +[sourcify-contract-verify]: https://docs.sourcify.dev/docs/how-to-verify/ +[ethereum-contract-verify]: https://ethereum.org/en/developers/docs/smart-contracts/verifying/ + +## Troubleshooting + +### Etherscan error with hardhat-verify + + - **Cause**: hardhat-verify tries to verify a contract on Etherscan for an unsupported network. + - **Solution**: Disable Etherscan verification with + ``` + etherscan: { + // Enabled by default (not supported on Sapphire) + enabled: false + }, + ``` + diff --git a/redirects.ts b/redirects.ts index 29a6cf214c..7251c9cf3b 100644 --- a/redirects.ts +++ b/redirects.ts @@ -284,6 +284,10 @@ export const redirectsOptions: Options = { { to: '/dapp/tools/band', from: '/dapp/emerald/integrating-band-oracle-smart-contract', // #907 Move Band oracle to Tools section + }, + { + to: '/dapp/tools/verification', + from: '/dapp/sapphire/verification', // #1054 Move Sapphire verification to Tools section } ], createRedirects(existingPath) { diff --git a/sidebarDapp.ts b/sidebarDapp.ts index 871b91165d..782f3a36af 100644 --- a/sidebarDapp.ts +++ b/sidebarDapp.ts @@ -20,7 +20,6 @@ export const sidebarDapp: SidebarsConfig = { 'dapp/sapphire/guide', 'dapp/sapphire/browser', 'dapp/sapphire/authentication', - 'dapp/sapphire/verification', 'dapp/sapphire/gasless', 'dapp/sapphire/addresses', 'dapp/sapphire/deployment', @@ -123,9 +122,10 @@ export const sidebarDapp: SidebarsConfig = { }, items: [ 'dapp/tools/abi-playground', + 'dapp/tools/verification', 'dapp/tools/band', 'dapp/tools/localnet', - 'dapp/tools/remix' + 'dapp/tools/remix', ], }, ],