Deploy a Smart Contract on the Polygon Mumbai network with AMB Access and Hardhat Ignition

8 minute read
Content level: Foundational
2

Learn how to deploy a smart contract on Polygon Mumbai with Amazon Managed Blockchain (AMB) Access and Hardhat Ignition

Introduction

In this tutorial, you'll learn how to create, compile, and deploy a simple smart contract on the Polygon Mumbai testnet using Amazon Managed Blockchain (AMB) Access. Hardhat Ignition is a declarative system that is utilized to handle the compilation and deployment of smart contracts. This tutorial is ideal for developers beginning their journey in blockchain development.

Prerequisites
  • Node.js (version 18 or above)
  • A text editor (such as Visual Studio Code)
  • Basic knowledge of Polygon and smart contracts
  • Installation of the AWS Command Line Interface (CLI).
    • Run the command aws configure to set the variables for your IAM User’s Access Key ID, Secret Access Key, and Region.
      • Ensure that this User has the appropriate IAM permissions for AMB Access Polygon. For this tutorial, you can use the AmazonManagedBlockchainFullAccess managed policy.

Step 1: Setting up the project

  1. Create a new directory for your project and change into it by running the following command in your terminal:
mkdir HelloWorldContract && cd HelloWorldContract
  1. Run the following command to initialize a new Node.js project:
npm init -y
  1. Install Hardhat Ignition and other necessary dependencies by running this command:
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-ignition-ethers web3 @aws-sdk/client-managedblockchain dotenv
  1. Set up a Hardhat project by executing this command. Choose the option, Create an empty hardhat.config.js:
npx hardhat init

Step 2: Write the Smart Contract

  1. Create a contracts directory containing a file named HelloWorld.sol at the root of your project with the following command:
mkdir contracts && touch contracts/HelloWorld.sol
  1. Copy the following code into the HelloWorld.sol file:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract HelloWorld {
    string public greeting;

    constructor() {
        greeting = "Hello, World!";
    }

    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }

    function getGreeting() public view returns (string memory) {
        return greeting;
    }
}

Step 3: Polygon account creation and environment variable setup

The following script automates the following tasks:

  1. Creation of a Polygon account (public/private key pair).
  2. Retrieval or creation of an AMB (Amazon Managed Blockchain) Mumbai Accessor token.
    • The script first checks for any existing Polygon Mumbai Accessor tokens in your AWS account. If an available token is found, it will be reused. Otherwise, a new Accessor token will be created.
  3. Configuration of an AMB Access Polygon Mumbai endpoint with your Accessor token.
    • Your configured endpoint will allow you to make JSON-RPC calls to the Polygon Mumbai testnet with web3.js.

Warning: Never share or expose your account’s private key or Accessor token publicly. It is important to note that the hardhat.config.js file is utilizing a locally stored private key and should not be used in production environments, as it poses a security risk. You should only use accounts that do not have any actual funds and only conduct transactions on the Mumbai testnet to avoid the risk of losing actual funds.

Create a new file (e.g init.js) in the root of your directory and copy the following code:

const fs = require('fs').promises;
const { Web3 } = require('web3');
const { ManagedBlockchainClient, CreateAccessorCommand, ListAccessorsCommand, GetAccessorCommand } = require("@aws-sdk/client-managedblockchain");

const network = "POLYGON_MUMBAI";

async function createAccount(accessEndpoint) {
    const web3 = new Web3(accessEndpoint);
    const account = web3.eth.accounts.create();
    return account;
}

async function getExistingAccessor(client) {
    try {
        const response = await client.send(new ListAccessorsCommand({ NetworkType: network }));

        for (const accessor of response.Accessors) {
            if (accessor.Status === "AVAILABLE") {
                const accessorResponse = await client.send(new GetAccessorCommand({ AccessorId: accessor.Id }));
                return accessorResponse.Accessor;
            }
        }
    } catch (error) {
        console.error('Error retrieving existing Accessor. Please double check your AWS credentials.', error);
        throw error;
    }
    return null;
}

async function createAccessor() {
    const client = new ManagedBlockchainClient();
    const existingAccessor = await getExistingAccessor(client);

    if (existingAccessor) {
        console.log('Using existing Accessor token.');
        return {
            billingToken: existingAccessor.BillingToken
        };
    }
    else {
        console.log('Creating a new Accessor token.');
    }

    try {
        const input = {
            AccessorType: "BILLING_TOKEN",
            NetworkType: network,
        };
        const command = new CreateAccessorCommand(input);
        const response = await client.send(command);
        return {
            billingToken: response.BillingToken,
        };
    } catch (error) {
        console.error('Error creating Accessor token:', error);
        throw error;
    }
}

async function main() {
    try {
        console.log('Creating or retrieving AMB Access Polygon Accessor token...');
        const accessor = await createAccessor();
        const accessEndpoint = `https://mumbai-testnet.polygon.managedblockchain.us-east-1.amazonaws.com?billingtoken=${accessor.billingToken}`;
        console.log('Creating account...');
        const account = await createAccount(accessEndpoint);
        const dataToSave = `PUBLIC_ADDRESS=${account.address}\nPRIVATE_KEY=${account.privateKey}\nAMB_ACCESS_POLYGON_MUMBAI=${accessEndpoint}`;
        await fs.writeFile('.env', dataToSave);
        console.log('Account and Accessor token created or retrieved. Details saved to .env file.');
        console.log(`Fund your newly created account (${account.address}) with testnet Polygon using a public faucet.`);
    } catch (error) {
        console.error('Setup failed:', error);
    }
}

main();

Execute the script by running:

node init.js

Your public address, private key, and endpoint for AMB Access Polygon Mumbai have been securely stored in a generated .env file.

Note: If you would like to use an existing account, modify the PUBLIC_ADDRESS and PRIVATE_KEY variables in the .env file.

Step 4: Fund your testnet Polygon account

Use a public faucet (such as Alchemy’s) to request a small amount of testnet Polygon to your newly created account's public address.

Step 5: Create the Hardhat Ignition Module

  1. Setup the deployment module directory in the root of your project with the following command:
mkdir -p ignition/modules && touch ignition/modules/DeployHelloWorld.js
  1. Copy the following code into the DeployHelloWorld.js file:
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");

module.exports = buildModule("DeployHelloWorld", (m) => {
    const helloWorld = m.contract("HelloWorld", []);

    return { helloWorld };
});
  1. Replace the hardhat.config.js file contents with the following code:
require("dotenv").config();
require("@nomicfoundation/hardhat-ignition-ethers");

module.exports = {
  solidity: "0.8.19",
  networks: {
    mumbai: {
      url: process.env.AMB_ACCESS_POLYGON_MUMBAI,
      // DO NOT USE AN ACCOUNT YOU USE ON MAINNET OR AN ACCOUNT THAT HAS ACTUAL FUNDS
      accounts: [process.env.PRIVATE_KEY]
    },
  },
};

Step 6: Compile and deploy your smart contract

  1. Run the following command to compile and deploy your smart contract:
npx hardhat ignition deploy ignition/modules/DeployHelloWorld.js --network mumbai
  1. Save your contract’s address in the .env file:
CONTRACT_ADDRESS=your-contract-address
  1. By running the following command, you will be taken to the contract page on the Polygon Mumbai blockchain explorer:
source .env && open https://mumbai.polygonscan.com/address/$CONTRACT_ADDRESS

With the successful deployment of your smart contract, explore Interact with your Smart Contract on Polygon Mumbai with Amazon Managed Blockchain (AMB) Access to learn how to read from and write data to your contract.

Optional: Verifying your contract on Polygon Scan

Important: If your smart contract's code is identical to the one used in this tutorial and has not been altered, automatic verification may occur. This is due to there being an existing similar contract on the Polygon Mumbai network.

If the contract was modified from the example or you want to verify it yourself, then follow the instructions below

  1. You first need to obtain an API Key by visiting the Polygon Scan website.
  2. If you're not registered, create an account, or log in if you already have one.
  3. In the account dashboard, go to the "API Keys" section.
  4. Click on "Add" to generate a new API key.
  5. Name your key for easy identification, such as "AMB Access Hardhat". After creation, the API key will be listed on the page.
  6. In your project's root directory, locate your .env file.
  7. Add a new variable named VERIFY_KEY and assign your Polygon Scan API key as its value:
VERIFY_KEY=your-polygon-scan-api-key

Integrate the VERIFY_KEY from your .env file into the hardhat.config.js file to use it with Polygon Scan:

require("dotenv").config();
require("@nomicfoundation/hardhat-ignition-ethers");

module.exports = {
  solidity: "0.8.19",
  networks: {
    mumbai: {
      url: process.env.AMB_ACCESS_POLYGON_MUMBAI,
      // DO NOT USE AN ACCOUNT YOU USE ON MAINNET OR AN ACCOUNT THAT HAS ACTUAL FUNDS
      accounts: [process.env.PRIVATE_KEY]
    },
  },
  etherscan: {
    apiKey: process.env.VERIFY_KEY,
  },
};

Run the following command to verify your smart contract:

npx hardhat ignition verify chain-80001

Conclusion

This tutorial guided you through the deployment of a smart contract on the Polygon Mumbai testnet, utilizing Amazon Managed Blockchain (AMB) Access Polygon and Hardhat Ignition. Remember to prioritize security, especially with private keys and your Accessor token.

Please leave a comment below if you have any questions. If you would like to learn more about AMB Access Polygon, you can refer to the documentation.