Skip to main content

Verify a smart contract

Overview

Verifying a smart contract is a crucial step to ensure the integrity and security of the Ronin network. The verification involves inspecting the contract's source code to ensure that it is bug-free, secure, and will perform as expected. We encourage the contract deployers to verify their contract by submitting the source code and metadata to our internal Sourcify service.

Verify using Hardhat

Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. hardhat-deploy is a deployment plugin for Hardhat that helps you automate the deployment of your smart contracts.

With hardhat-deploy, you can verify the source code of your smart contract using the following methods:

  • Using the CLI
  • Using the deployment script

Option 1. Using the CLI

If your smart contract project uses hardhat-deploy as a dependency, specify the endpoint and network before verifying by using the hardhat sourcify command:

hardhat sourcify --endpoint https://sourcify.roninchain.com/server/ --network <ronin>
note

Do not drop the trailing slash / in the endpoint URL.

For more information, see hardhat-sourcify.

Option 2. Using the script

  1. Save the following script to deploy/verify-contract.ts.
deploy/verify-contract.ts
import { TASK_SOURCIFY } from 'hardhat-deploy';
import { network } from 'hardhat';
import { HardhatRuntimeEnvironment } from 'hardhat/types';

const deploy = async (hre: HardhatRuntimeEnvironment) => {
if (network.name == 'ronin' || network.name == 'saigon') {
await hre.run(TASK_SOURCIFY, {
endpoint: 'https://sourcify.roninchain.com/server',
});
}
};

deploy.tags = ['VerifyContracts'];
deploy.runAtTheEnd = true;

export default deploy;
  1. Include this script in the actual deployment script's dependencies. For example:
deploy/sample-contract.ts
deploy.dependencies = ['VerifyContracts'];

Verify using Foundry

Foundry is a command-line tool that helps you verify the source code of your smart contract on the Ronin network.

To verify your smart contract using Foundry, follow these steps:

  1. Install Foundry by following the installation guide.
  2. Run the following command:
forge verify-contract --verifier sourcify --verifier-url https://sourcify.roninchain.com/server/ --chain-id <CHAIN> <ADDRESS> <CONTRACT>

Replace the following placeholders with the actual values:

  • <CHAIN>: The chain to which the contract is deployed, such as 2021 for the Ronin mainnet or 2020 for the Saigon testnet.
  • <ADDRESS>: The address of the smart contract.
  • <CONTRACT>: The path to the contract in the format <path>:<contract>, such as src/SampleContract.sol:SampleContract.

You should see output similar to this:

Start verifying contract `0xADDRESS` deployed on 2021

Submitting verification for [SampleContract] "0xADDRESS".
Contract successfully verified

For the full list of options you can use with the forge-verify-contract command, see the forge verify-contract documentation.

Verify using Sourcify UI

Step 1. Locate smart contract metadata

Smart contract's metadata is automatically generated by the Solidity compiler in the form of a .json file. It contains information about the compiled smart contract. The metadata is located in different locations depending on the tool you use to compile smart contracts.

Solidity compiler contract metadata

  1. If you use solc for compiling, then to print out the contract's metadata, run the following command:
solc <CONTRACT>.sol --metadata

Replace <CONTRACT> with the name of the contract file.

You should see output similar to this:

======= Token.sol:Token =======
Metadata:
{"compiler":{"version":"0.8.20+commit.a1b79de6"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{"balanceOf(address)":{"notice":"Read only function to retrieve the token balance of a given account. The `view` modifier indicates that it doesn't modify the contract's state, which allows us to call it without executing a transaction."},"constructor":{"notice":"Contract initialization."},"transfer(address,uint256)":{"notice":"A function to transfer tokens. The `external` modifier makes a function *only* callable from *outside* the contract."}},"version":1}},"settings":{"compilationTarget":{"Token.sol":"Token"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"Token.sol":{"keccak256":"0xa79117cae1147d7d93c6e5653e26d2ce4a6669f211a7de27ffc2ac61c57a115b","license":"UNLICENSED","urls":["bzz-raw://1b28ac474b44450104fc99400a70947517e0869274a3537c9d0ea8047d7b8146","dweb:/ipfs/QmYreFmttckn7Mru8z1oe89sVbWVUBd2WxvX8w12yreaFF"]}},"version":1}
  1. Copy the JSON object starting at {”compiler”:... to a new file and save it as metadata.json.
  2. Upload your metadata.json file and the source code of your contract in the .sol format to Sourcify.

Hardhat contract metadata

If you use Hardhat for compiling your smart contract, then after running the hardhat compile command, you can find the metadata file in the artifacts/build-info directory. Hardhat includes the source code in the metadata file. You can upload just this .json file to Sourcify.

Step 2. Submit information

  1. After you find the metadata and source code, upload them to Sourcify. If your files are valid, a contract's details form is displayed on the right side of the page.
  2. To complete the verification process, fill out the smart contract address and select the chain to which it is deployed.

When verification is complete, a Verification successful! message appears (pictured).

To interact with the example contract on the Ronin app and view its source code, visit https://saigon-app.roninchain.com/address/ronin:6df3a52ca77b2b785b9d9cb454725969e006c718?t=contract.

Verify using API

The following public API endpoints are available for verifying the source code of a smart contract.

POST https://sourcify.roninchain.com/server/verify
POST https://sourcify.roninchain.com/server/verify/create2

For more information on how to use these API endpoints, see Verification API.

See also

Smart contract guidelines