Contents

Deploy Smart Contract to Ronin Network with Hardhat

Initiate project

  • mkdir play-hardhat && cd play-hardhat
    mkdir contracts
    mkdir scripts
    npm init -y
    yarn add -D hardhat @openzeppelin/hardhat-upgrades @nomicfoundation/hardhat-verify @nomicfoundation/hardhat-ethers
    yarn hardhat init
    

Configuration

  • // hardhat.config.ts
    import type { HardhatUserConfig } from 'hardhat/config';
    import { MNEMONIC, PRIVATE_KEY } from './secrets.json';
    import '@openzeppelin/hardhat-upgrades';
    import '@nomicfoundation/hardhat-verify';
    import '@nomicfoundation/hardhat-ethers';
    
    const config: HardhatUserConfig = {
      solidity: {
        version: '0.8.27',
        settings: {
          optimizer: {
            enabled: true,
            runs: 200,
          },
        },
      },
      networks: {
        ronin: {
          chainId: 2020,
          url: 'https://api.roninchain.com/rpc',
          gasPrice: 20_000_000_000,
          accounts: [PRIVATE_KEY],
        },
        saigon: {
          chainId: 2021,
          url: 'https://saigon-testnet.roninchain.com/rpc',
          gasPrice: 20_000_000_000,
          accounts: {
            MNEMONIC,
          },
        },
      },
      sourcify: {
        enabled: true,
        apiUrl: 'https://sourcify.roninchain.com/server/',
      },
      // etherscan enabled default value true, have to override it to false in order to use sourcify
      etherscan: {
        enabled: false,
      },
    };
    
    export default config;
    

Deploy

  • // scripts/deploy.ts
    // yarn hardhat run --network saigon scripts/deploy.ts
    import { ethers } from 'hardhat';
    
    async function main() {
      const name = 'Box';
      const Contract = await ethers.getContractFactory(name);
    
      console.log(`Deploying ${name}...`);
      const proxy = await upgrades.deployProxy(Contract, [66], {
        initializer: 'store',
        kind: 'uups',
      });
      await proxy.waitForDeployment();
      const proxyAddress = await proxy.getAddress();
      const implAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress);
      console.log(`${name} deployed to:`, implAddress);
      console.log(`Proxy deployed to:`, proxyAddress);
    
      // const box = await Box.deploy();
      // await box.waitForDeployment();
      // const proxy = await ERC1967Proxy.deploy(await box.getAddress(), Box.interface.encodeFunctionData('store', [66]));
    
      // await proxy.waitForDeployment();
      // console.log('Box deployed to:', await box.getAddress());
      // console.log('Proxy deployed to:', await proxy.getAddress());
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

Import

  • This process will create .openzeppelin folder in the root directory
  • // scripts/import.ts
    // yarn hardhat run --network saigon scripts/import.ts
    import { ethers, upgrades } from 'hardhat';
    
    async function main() {
      const Box = await ethers.getContractFactory('Box');
      console.log('Importing Box...');
      await upgrades.forceImport('<PROXY_ADDRESS>', Box, {
        kind: 'uups',
      });
      console.log('Imported!');
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

Upgrade

  • // scripts/upgrade.ts
    // yarn hardhat run --network saigon scripts/upgrade.ts
    import { ethers, upgrades } from 'hardhat';
    
    async function main() {
      const BoxV2 = await ethers.getContractFactory('BoxV2');
    
      console.log('Upgrading to BoxV2...');
      await upgrades.upgradeProxy('<PROXY_ADDRESS>', BoxV2, {
        kind: 'uups',
        redeployImplementation: 'always',
      });
      console.log('Upgraded!');
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

Verify