# Hardhat Developer Workflow

### Introduction <a href="#introduction" id="introduction"></a>

In this tutorial, we'll walk through the [Hardhat development environment](https://hardhat.org/) in the context of launching a pooled staking DAO contract. We'll walk through the typical developer workflow in detail from start to finish.

We'll assemble the components of the staking DAO and compile the necessary contracts. Then, we'll build a test suite with a variety of test cases relevant to our staking DAO, and run it against a local development node. Finally, we'll deploy the staking DAO to both Phronbase Alpha and Phron and verify the contracts via the Hardhat Etherscan plugin. If this is your first time exploring Hardhat, you may wish to start with the introduction to Hardhat guide.

The information presented herein is for informational purposes only and has been provided by third parties. Phron does not endorse any project listed and described on the Phron docs website.

### Checking Prerequisites <a href="#checking-prerequisites" id="checking-prerequisites"></a>

To get started, you will need the following:

* A Phron account funded with DEV. You can get DEV tokens for testing on Phron once every 24 hours from the Phron Faucet
* A Phronscan API Key
* For the Testing section, you'll need to have a local Phron node up and running
* To test out the examples in this guide on Phron, you will need to have your own endpoint and API key, which you can get from one of the supported Endpoint Providers

### Creating a Hardhat Project <a href="#creating-a-hardhat-project" id="creating-a-hardhat-project"></a>

You will need to create a Hardhat project if you don't already have one. You can create one by completing the following steps:

1. Create a directory for your project

   ```bash
   mkdir stakingDAO && cd stakingDAO
   ```
2. Initialize the project which will create a `package.json` file

   ```bash
   npm init -y
   ```
3. Install Hardhat

   ```bash
   npm install hardhat
   ```
4. Create a project

   ```bash
   npx hardhat init
   ```

> ### Note
>
> `npx` is used to run executables installed locally in your project. Although Hardhat can be installed globally, it is recommended to install it locally in each project so that you can control the version on a project by project basis.

1. A menu will appear allowing you to create a new project or use a sample project. For this example, you can choose **Create an empty hardhat.config.js**

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash"><strong>npx hardhat init888    888                      888 888               888888    888                      888 888               888888    888                      888 888               8888888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888888    888     "88b 888P"  d88" 888 888 "88b     "88b 888888    888 .d888888 888    888  888 888  888 .d888888 888888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888
</strong>👷 Welcome to Hardhat v2.22.2 👷‍
 What do you want to do? …  Create a JavaScript project   Create a TypeScript project   Create a TypeScript project (with Viem)   Quit
</code></pre>

This will create a Hardhat config file (`hardhat.config.js`) in your project directory.

### Add Smart Contracts <a href="#add-smart-contracts" id="add-smart-contracts"></a>

The smart contract featured in this tutorial is more complex than the one in the Introduction to Hardhat but the nature of the contract means it's perfect to demonstrate some of the advanced capabilities of Hardhat. `DelegationDAO.sol` is a pooled staking DAO that uses `StakingInterface.sol` to autonomously delegate to a collator when it reaches a determined threshold. Pooled staking contracts such as `DelegationDAO.sol` allow delegators with less than the protocol minimum bond to join together to delegate their pooled funds and earn a share of staking rewards.

> ### Note
>
> `DelegationDAO.sol` is unreviewed and unaudited. It is designed only for demonstration purposes and not intended for production use. It may contain bugs or logic errors that could result in loss of funds.

To get started, take the following steps:

1. Create a `contracts` directory to hold your project's smart contracts

   ```bash
   mkdir contracts
   ```
2. Create a new file called `DelegationDAO.sol`

   ```bash
   touch contracts/DelegationDAO.sol
   ```
3. Copy and paste the contents of [DelegationDAO.sol](https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-intro-course-resources/main/delegation-dao-lesson-one/DelegationDAO.sol) into `DelegationDAO.sol`
4. Create a new file called `StakingInterface.sol` in the `contracts` directory

   ```bash
   touch contracts/StakingInterface.sol
   ```
5. Copy and paste the contents of [StakingInterface.sol](https://raw.githubusercontent.com/moonbeam-foundation/moonbeam/master/precompiles/parachain-staking/StakingInterface.sol) into `StakingInterface.sol`
6. `DelegationDAO.sol` relies on a couple of standard [OpenZeppelin](https://www.openzeppelin.com/) contracts. Add the library with the following command:

   ```bash
   npm install @openzeppelin/contracts
   ```

### Hardhat Configuration File <a href="#hardhat-configuration-file" id="hardhat-configuration-file"></a>

When setting up the `hardhat.config.js` file, we'll need to import a few plugins that we'll use throughout this guide. So to get started, we'll need the [Hardhat Toolbox plugin](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-toolbox), which conveniently bundles together Hardhat plugins that can be used to deploy and interact with contracts using Ethers, test contracts with Mocha and Chai, verify contracts with Etherscan, and more. You can run the following command to install the plugin:

```bash
npm install --save-dev @nomicfoundation/hardhat-toolbox 
```

If you're curious about additional Hardhat plugins, here is [a complete list of official Hardhat plugins](https://hardhat.org/hardhat-runner/plugins).

For the examples in this guide, you'll need to add your private keys for your two accounts on Phron. Since some of the testing will be done on a development node, you'll also need to add the private keys of two of the prefunded development node accounts, which for this example, we can use Alice and Bob. In addition, you'll add your Phronscan API key, which can be used for Phron.

````javascript
You can modify the `hardhat.config.js` file to use any of the Phron networks:

=== "Phron"

    ```js
    phron: {
      url: 'INSERT_RPC_API_ENDPOINT', // Insert your RPC URL here
      chainId: 7744, // (hex: 0x504),
      accounts: [privateKey]
    },
    ```

=== "Phron"

    ```js
    phron: {
      url: 'INSERT_RPC_API_ENDPOINT', // Insert your RPC URL here
      chainId: 7744, // (hex: 0x505),
      accounts: [privateKey]
    },
    ```

=== "Phron"

    ```js
    phron: {
      url: 'https://testnet.phron.ai',
      chainId: 7744, // (hex: 0x507),
      accounts: [privateKey]
    },
    ```

=== "Phron Dev Node"

    ```js
    dev: {
      url: 'http://127.0.0.1:9944',
      chainId: 7744, // (hex: 0x501),
      accounts: [privateKey]
    },
    ```
````

1. Add your Phronscan API key, which is required for the verification steps we'll be taking later in this tutorial

```javascript
// 1. Import the Hardhat Toolbox plugin
require('@nomicfoundation/hardhat-toolbox');
require('@nomicfoundation/hardhat-ignition-ethers');

// 2. Create variables for your private keys from your pre-funded Phronscan
// testing accounts and your Phronscan API key
const privateKey = 'INSERT_PRIVATE_KEY';
const privateKey2 = 'INSERT_ANOTHER_PRIVATE_KEY';
const phronscanAPIKey = 'INSERT_PHRONSCAN_API_KEY';

module.exports = {
  // 3. Specify the Solidity version
  solidity: '0.8.20',
  networks: {
    // 4. Add the Phron network specification
    phron: {
      url: 'https://testnet.phron.ai',
      chainId: 7744, // 0x507 in hex
      accounts: [privateKey, privateKey2],
    },
    dev: {
      url: 'http://127.0.0.1:9944',
      chainId: 7744, // 0x501 in hex
      accounts: [
        '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133', // Alice's PK
        '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b', // Bob's PK
      ],
    },
    phron: {
      url: 'https://testnet.phron.ai', // Or insert your own RPC URL here
      chainId: 1284, // 0x504 in hex
      accounts: [privateKey, privateKey2],
    },
  },
  // 5. Set up your Phronscan API key for contract verification
  etherscan: {
    apiKey: {
      phron: phronscanAPIKey, 
      phrons: phronscanAPIKey, 
    },
  },
};
```

> ### Note
>
> Any real funds sent to the Alice and Bob development accounts will be lost immediately. Take precautions to never send MainNet funds to exposed development accounts.

You're now ready to move on to compilation and testing.

### Compiling the Contract <a href="#compiling-the-contract" id="compiling-the-contract"></a>

To compile the contract you can simply run:

```bash
npx hardhat compile
```

{% code overflow="wrap" %}

```sh
npx hardhat compileCompiled 8 Solidity files successfully (evm target: paris).
```

{% endcode %}

After compilation, an `artifacts` directory is created: it holds the bytecode and metadata of the contract, which are `.json` files. Adding this directory to your `.gitignore` is a good idea.

### Testing <a href="#testing" id="testing"></a>

A robust smart contract development workflow is complete with a testing suite. Hardhat has a number of tools that make it easy to write and run tests. In this section, you'll learn the basics of testing your smart contracts and some more advanced techniques.

Hardhat tests are typically written with Mocha and Chai. [Mocha](https://mochajs.org/) is a JavaScript testing framework and [Chai](https://www.chaijs.com/) is a BDD/TDD JavaScript assertion library. BDD/TDD stands for behavior and test-driven development respectively. Effective BDD/TDD necessitates writing your tests *before* writing your smart contract code. The structure of this tutorial doesn't strictly follow these guidelines, but you may wish to adopt these principles in your development workflow. Hardhat recommends using [Hardhat Toolbox](https://hardhat.org/hardhat-runner/docs/advanced/migrating-from-hardhat-waffle), a plugin that bundles everything you need to get started with Hardhat, including Mocha and Chai.

Because we will initially be running our tests on a local Phron node, we need to specify Alice's address as the address of our target collator (Alice's account is the only collator for a local development node):

```
0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac
```

If instead you prefer to run your tests against Phron, you can choose the below collator, or any other collator on Phron you would like the DAO to delegate to:

```
0x12E7BCCA9b1B15f33585b5fc898B967149BDb9a5
```

#### Configuring the Test File <a href="#configuring-the-test-file" id="configuring-the-test-file"></a>

To set up your test file, take the following steps:

1. Create a `tests` directory

   ```bash
   mkdir tests
   ```
2. Create a new file called `Dao.js`

   ```bash
   touch tests/Dao.js
   ```
3. Then copy and paste the contents below to set up the initial structure of your test file. Be sure to read the comments, as they can clarify the purpose of each line

   ```jsx
   // Import Ethers
   const { ethers } = require('hardhat');

   // Import Chai to use its assertion functions here
   const { expect } = require('chai');

   // Indicate Alice's address as the target collator on local development node
   const targetCollator = '0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac';
   ```

#### Deploying a Staking DAO for Testing <a href="#deploying-a-staking-dao-for-testing" id="deploying-a-staking-dao-for-testing"></a>

Before we can run any test cases we'll need to launch a staking DAO with an initial configuration. Our setup here is relatively simple - we'll be deploying a staking DAO with a single administrator (the deployer) and then adding a new member to the DAO. This simple setup is perfect for demonstration purposes, but it's easy to imagine more complex configurations you'd like to test, such as a scenario with 100 DAO members or one with multiple admins of the DAO.

Mocha's `describe` function enables you to organize your tests. Multiple `describe` functions can be nested together. It's entirely optional but can be useful, especially in complex projects with many test cases. You can read more about constructing tests and [getting started with Mocha](https://mochajs.org/#getting-started) on the Mocha docs site.

We'll define a function called `deployDao` containing the setup steps for our staking DAO. To configure your test file, add the following snippet:

{% code overflow="wrap" %}

```jsx
// The describe function receives the name of a section of your test suite, and a callback. The callback must define the tests of that section. This callback can't be an async function
describe('Dao contract', function () {
  let wallet1, wallet2;

  before(async function () {
    // Get signers we defined in Hardhat config
    const signers = await ethers.getSigners();
    wallet1 = signers[0];
    wallet2 = signers[1];
  });

  async function deployDao() {
    const delegationDaoFactory = await ethers.getContractFactory(
      'DelegationDAO',
      wallet2
    );

    // Deploy the staking DAO and wait for the deployment transaction to be confirmed
    try {
      const deployedDao = await delegationDaoFactory.deploy(
        targetCollator,
        wallet2.address
      );
      await deployedDao.waitForDeployment(); // Wait for the transaction to be mined
      return { deployedDao };
    } catch (error) {
      console.error('Failed to deploy contract:', error);
      return null; // Return null to indicate failure
    }
  }
  // Insert additional tests here
}); 
```

{% endcode %}

#### Writing your First Test Cases <a href="#writing-your-first-test-cases" id="writing-your-first-test-cases"></a>

First, you'll create a subsection called `Deployment` to keep the test file organized. This will be nested within the `Dao contract` describe function. Next, you'll define your first test case by using the `it` Mocha function. This first test checks to see that the staking DAO correctly stores the address of the target collator.

Add the snippet below to the end of your `Dao contract` function.

```solidity
// You can nest calls to create subsections
describe('Deployment', function () {
  // Mocha's it function is used to define each of your tests. It receives the test name, and a callback function. If the callback function is async, Mocha will await it. Test case to check that the correct target collator is stored
  it('should store the correct target collator in the DAO', async function () {
    const deployment = await deployDao();
    if (!deployment || !deployment.deployedDao) {
      throw new Error('Deployment failed; DAO contract was not deployed.');
    }
    const { deployedDao } = deployment;

    // The expect function receives a value and wraps it in an assertion object.
    // This test will pass if the DAO stored the correct target collator
    expect(await deployedDao.getTarget()).to.equal(
      '0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac'
    );
  });
  // The following test cases should be added here
});
```

Now, add another test case. When a staking DAO is launched, it shouldn't have any funds. This test verifies that is indeed the case. Go ahead and add the following test case to your `Dao.js` file:

```solidity
// Test case to check that the DAO has 0 funds at inception
it('should initially have 0 funds in the DAO', async function () {
  const { deployedDao } = await deployDao();
  // This test will pass if the DAO has no funds as expected before any contributions
  expect(await deployedDao.totalStake()).to.equal(0);
});
```

#### Function Reverts <a href="#function-reverts" id="function-reverts"></a>

Now, you'll implement a more complex test case with a slightly different architecture. In prior examples, you've verified that a function returns an expected value. In this one, you'll be verifying that a function reverts. You'll also change the caller's address to test an admin-only function.

In the staking DAO contract, only admins are authorized to add new members to the DAO. One could write a test that checks to see if the admin is authorized to add new members but a more important test is to ensure that *non-admins* can't add new members. To run this test case under a different account, you will ask for another address when you call `ethers.getSigners()` and specify the caller in the assertion with `connect(member1)`. Finally, after the function call you'll append `.to.be.reverted` to indicate that the test case is successful if the function reverts. And if it doesn't revert, it's a failed test!

```solidity
// Test case to check that non-admins cannot grant membership
it('should not allow non-admins to grant membership', async function () {
  const { deployedDao } = await deployDao();
  // Connect the non-admin wallet to the deployed contract
  const deployedDaoConnected = deployedDao.connect(wallet1);
  const tx = deployedDaoConnected.grant_member(
    '0x0000000000000000000000000000000000000000'
  );

  // Check that the transaction reverts, not specifying any particular reason
  await expect(tx).to.be.reverted;
});
```

#### Signing Transactions from Other Accounts <a href="#signing-transactions-from-other-accounts" id="signing-transactions-from-other-accounts"></a>

For this example, you'll verify whether the newly added DAO member can call the `check_free_balance()` function of staking DAO, which has an access modifier such that only members can access it.

```solidity
// Test case to check that members can access member only functions
it('should only allow members to access member-only functions', async function () {
  const { deployedDao } = await deployDao();

  // Connect the wallet1 to the deployed contract and grant membership
  const deployedDaoConnected = deployedDao.connect(wallet2);
  const grantTx = await deployedDaoConnected.grant_member(wallet1.address);
  await grantTx.wait();

  // Check the free balance using the member's credentials
  const checkTx = deployedDaoConnected.check_free_balance();

  // Since check_free_balance() does not modify state, we expect it not to be reverted and check the balance
  await expect(checkTx).to.not.be.reverted;
  expect(await checkTx).to.equal(0);
});
```

And that's it! You're now ready to run your tests!

#### Running your Tests <a href="#running-your-tests" id="running-your-tests"></a>

If you've followed all of the prior sections, your [`Dao.js`](https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-intro-course-resources/main/delegation-dao-lesson-one/Dao.js) test file should be all set to go.

<details>

<summary>Dao.js</summary>

```jsx
// Import Ethers
const { ethers } = require('hardhat');
// Import Chai to use its assertion functions here
const { expect } = require('chai');

// Indicate the collator the DAO wants to delegate to
// For Phron Local Node, use: 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac
// For Phron, use: 0x12E7BCCA9b1B15f33585b5fc898B967149BDb9a5
const targetCollator = 'INSERT_COLLATOR_ADDRESS';

// The describe function receives the name of a section of your test suite, and a
// callback. The callback must define the tests of that section. This callback
// can't be an async function
describe('Dao contract', function () {
  let wallet1, wallet2;

  before(async function () {
    // Get signers we defined in Hardhat config
    const signers = await ethers.getSigners();
    wallet1 = signers[0];
    wallet2 = signers[1];
  });

  async function deployDao() {
    const delegationDaoFactory = await ethers.getContractFactory(
      'DelegationDAO',
      wallet2
    );

    // Deploy the staking DAO and wait for the deployment transaction to be confirmed
    try {
      const deployedDao = await delegationDaoFactory.deploy(
        targetCollator,
        wallet2.address
      );
      await deployedDao.waitForDeployment(); // Correct way to wait for the transaction to be mined
      return { deployedDao };
    } catch (error) {
      console.error('Failed to deploy contract:', error);
      return null; // Return null to indicate failure
    }
  }

  describe('Deployment', function () {
    // Test case to check that the correct target collator is stored
    it('should store the correct target collator in the DAO', async function () {
      const deployment = await deployDao();
      if (!deployment || !deployment.deployedDao) {
        throw new Error('Deployment failed; DAO contract was not deployed.');
      }
      const { deployedDao } = deployment;
      expect(await deployedDao.getTarget()).to.equal(
        '0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac'
      );
    });

    // Test case to check that the DAO has 0 funds at inception
    it('should initially have 0 funds in the DAO', async function () {
      const { deployedDao } = await deployDao();
      expect(await deployedDao.totalStake()).to.equal(0);
    });

    // Test case to check that non-admins cannot grant membership
    it('should not allow non-admins to grant membership', async function () {
      const { deployedDao } = await deployDao();
      // Connect the non-admin wallet to the deployed contract
      const deployedDaoConnected = deployedDao.connect(wallet1);
      const tx = deployedDaoConnected.grant_member(
        '0x0000000000000000000000000000000000000000'
      );

      // Check that the transaction reverts, not specifying any particular reason
      await expect(tx).to.be.reverted;
    });

    // Test case to check that members can access member only functions
    it('should only allow members to access member-only functions', async function () {
      const { deployedDao } = await deployDao();

      // Connect the wallet1 to the deployed contract and grant membership
      const deployedDaoConnected = deployedDao.connect(wallet2);
      const grantTx = await deployedDaoConnected.grant_member(wallet1.address);
      await grantTx.wait();

      // Check the free balance using the member's credentials
      const checkTx = deployedDaoConnected.check_free_balance();

      // Since check_free_balance() does not modify state, we expect it not to be reverted and check the balance
      await expect(checkTx).to.not.be.reverted;
      expect(await checkTx).to.equal(0);
    });
  });
});
```

</details>

Since our test cases encompass mostly configuration and setup of the staking DAO and don't involve actual delegation actions, we'll be running our tests on a Phron development node (local node). Remember that Alice (`0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac`) is the only collator on a local development node. You can use the flag `--network phronbase` to run the tests using Phronbase. In that case, ensure your deployer address is sufficiently funded with DEV tokens.

Challenge

Try to create an additional test case that verifies the staking DAO successfully delegates to a collator once `minDelegationStk` is met. You must test this on Phron rather than a local development node.

First, make sure that your local Phron node is running by following the instructions for launching a local development node. Take precautions because you could inadvertently send real funds to the Alice and Bob development accounts, resulting in a loss of those funds.

You can run your tests with the following command:

```bash
npx hardhat test --network dev tests/Dao.js
```

If everything was set up correctly, you should see output like the following:

{% code overflow="wrap" %}

```bash
npx hardhat test --network dev tests/Dao.js

Dao contract Deployment ✅ The DAO should store the correct target collator (1624ms) ✅ The DAO should initially have 0 funds in it ✅ Non-admins should not be able to grant membership (150ms) ✅ DAO members should be able to access member only functions (132ms)

✅ 4 passing (2s)
```

{% endcode %}

### Deploying to Phron <a href="#deploying-to-phron" id="deploying-to-phron"></a>

In the following steps, we'll deploy the `DelegationDAO` to the Phron TestNet. Before deploying to Phron, double-check that you're not using the Alice and Bob accounts, which should only be used on a local development node.

As a side note, `DelegationDAO` relies on `StakingInterface.sol`, which is a Substrate-based offering unique to Phron networks. The Hardhat Network and forked networks are simulated EVM environments which do not include the Substrate-based precompiles like `StakingInterface.sol`. Therefore, `DelegationDAO` will not work properly if deployed to the local default Hardhat Network or a forked network.

To deploy `DelegationDAO`, you'll use Hardhat Ignition, a declarative framework for deploying smart contracts. Hardhat Ignition is designed to make it easy to manage recurring tasks surrounding smart contract deployment and testing. For more information about Hardhat Ignition and its architecture, be sure to check out the [Hardhat Ignition docs](https://hardhat.org/ignition/docs/getting-started#overview).

To set up the proper file structure for your Ignition module, create a folder named `ignition` and a subdirectory called `modules`. Then, add a new file to it called `DelegationDao.js`. You can take all three of these steps with the following command:

```bash
mkdir ignition ignition/modules && touch ignition/modules/DelegationDao.js
```

Next, you can write your Hardhat Ignition module. To get started, take the following steps:

1. Import the `buildModule` function from the Hardhat Ignition module
2. Export a module using `buildModule`
3. Specify the target collator candidate for the DAO to delegate to
4. Use the `getAccount` method to select the deployer account
5. Deploy `DelegationDAO.sol`
6. Return an object from the module. This makes the `DelegationDao` contract accessible for interaction in Hardhat tests and scripts

When all is said and done your deployment script should look similar to the following:

{% code overflow="wrap" %}

```solidity
// 1. Import the required function from the Hardhat Ignition module
const { buildModule } = require('@nomicfoundation/hardhat-ignition/modules');

// 2. Define and export your deployment module using `buildModule`
module.exports = buildModule('DelegationDAOModule', (m) => {
  // 3. Specify the target collator address for the DAO
  const targetCollator = '0x12E7BCCA9b1B15f33585b5fc898B967149BDb9a5';

  // 4. Use the `getAccount` method to select the deployer account
  const deployer = m.getAccount(0);

  // 5. Deploy the `DelegationDAO` contract
  const delegationDao = m.contract(
    'DelegationDAO',
    [targetCollator, deployer],
    {
      from: deployer,
    }
  );

  // 6. Return an object from the module including references to deployed contracts, allowing the contract to be accessible for interaction in Hardhat tests and scripts
  return { delegationDao };
});
```

{% endcode %}

To run the script and deploy the `DelegationDAO.sol` contract, use the following command, which requires you to specify the network name as defined in your `hardhat.config.js`. If you don't specify a network, Hardhat will deploy the contract to a local Hardhat network by default.

{% code overflow="wrap" %}

```bash
npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network phron --deployment-id INSERT_YOUR_NAME
```

{% endcode %}

You'll be prompted to confirm the network you wish to deploy to. After a few seconds after you confirm, the contract is deployed, and you'll see the contract address in the terminal.

{% code overflow="wrap" %}

```
npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network phron --deployment-id INSERT_YOUR_NAME
✅ Confirm deploy to network phron (1287)? … yesHardhat Ignition 🚀
Deploying [ DelegationDAOModule ]
Batch #1Executed DelegationDAOModule#DelegationDAO
[ DelegationDAOModule ] successfully deployed 🚀
Deployed Addresses
DelegationDAOModule#DelegationDAO - 0x69c555fE1A8D0916E6dab0629bd7530D4d2Be4D1
```

{% endcode %}

Congratulations, your contract is live on Phron! Save the address, as you will use it to interact with this contract instance in the next step.

### Verifying Contracts on Phron <a href="#verifying-contracts-on-moonbase-alpha" id="verifying-contracts-on-moonbase-alpha"></a>

Contract verification is an essential step of any developer's workflow, particularly in the theoretical example of this staking DAO. Potential participants in the DAO need to be assured that the smart contract works as intended - and verifying the contract allows anyone to observe and analyze the deployed smart contract.

While it's possible to verify smart contracts on the [Phronscan website](https://testnet.phronscan.io), the Hardhat Etherscan plugin enables us to verify our staking DAO in a faster and easier manner. It's not an exaggeration to say that the plugin dramatically simplifies the contract verification process, especially for projects that include multiple Solidity files or libraries.

Before beginning the contract verification process, you'll need to acquire a Phronscan API Key. Note that Phron use the same Phronscan API key, whereas you'll need a distinct API key for Phron.

To verify the contract, you will run the `ignition verify` command and pass the name of your deployment you set in the prior step.

```bash
npx hardhat ignition verify INSERT_YOUR_NAME
```

> ### Note
>
> If you're deploying `DelegationDAO.sol` verbatim without any changes, you may get an `Already Verified` error because Phronscan automatically recognizes and verifies smart contracts that have matching bytecode. Your contract will still show as verified, so there is nothing else you need to do. However, if you'd prefer to verify your own `DelegationDAO.sol`, you can make a small change to the contract (such as changing a comment) and repeating the compilation, deployment and verification steps.

In your terminal, you should see the source code for your contract was successfully submitted for verification. If the verification was successful, you should see **Successfully verified contract** and there will be a link to the contract code on Phronscan. If the plugin returns an error, double check that your API key is configured correctly and that you have specified all necessary parameters in the verification command. You can refer to the guide to the Hardhat Etherscan plugin for more information.

{% code overflow="wrap" %}

```bash
npx hardhat ignition verify INSERT_YOUR_NAME
Nothing to compileSuccessfully submitted source code for contract contracts/DelegationDAO.sol:DelegationDAO at 0x5D788B98E4A90F9642352B0b32694998e77cF4d7 for verification on the block explorer. Waiting for verification result...
Successfully verified contract DelegationDAO on Etherscan.
https://testnet.phronscan.io/address/0x5D788B98E4A90F9642352B0b32694998e77cF4d7#code
```

{% endcode %}

### Deploying to Production on Phron Mainnet <a href="#deploying-to-production-on-moonbeam-mainnet" id="deploying-to-production-on-moonbeam-mainnet"></a>

> ### Note
>
> `DelegationDAO.sol` is unreviewed and unaudited. It is designed only for demonstration purposes and not intended for production use. It may contain bugs or logic errors that could result in loss of funds.

In the following steps, we'll be deploying the `DelegationDAO` contract to the Phron MainNet network. Remember to add the Phron network to your `hardhat.config.js` and update the private keys of your accounts on Phron if you haven't done so already. Before deploying `DelegationDAO` to Phron, we need to change the address of the target collator, since our target collator on Phron does not exist on Phron. Head to your deploy script and change the target collator to `0x1C86E56007FCBF759348dcF0479596a9857Ba105` or another Phron collator of your choice. Your deployment script, named `DelegationDao.js`, should thus look like the following:

```javascript
// 1. Import the required function from the Hardhat Ignition module
const { buildModule } = require('@nomicfoundation/hardhat-ignition/modules');

// 2. Define and export your deployment module using `buildModule`
module.exports = buildModule('DelegationDAOModule', (m) => {
  // 3. Specify the target collator address for the DAO
  const targetCollator = '0x1C86E56007FCBF759348dcF0479596a9857Ba105';

  // 4. Use the `getAccount` method to select the deployer account
  const deployer = m.getAccount(0);

  // 5. Deploy the `DelegationDAO` contract
  const delegationDao = m.contract(
    'DelegationDAO',
    [targetCollator, deployer],
    {
      from: deployer,
    }
  );

  // 6. Return an object from the module including references to deployed contracts, allowing the contract to be accessible for interaction in Hardhat tests and scripts
  return { delegationDao };
});
```

To run the script and deploy the `DelegationDAO.sol` contract, use the following command, which requires you to specify the network name as defined in your `hardhat.config.js`. If you don't specify a network, Hardhat will deploy the contract to a local Hardhat network by default.

{% code overflow="wrap" %}

```bash
npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network phron --deployment-id INSERT_YOUR_NAME
```

{% endcode %}

You'll be prompted to confirm the network you wish to deploy to. After a few seconds after you confirm, the contract is deployed, and you'll see the contract address in the terminal.

{% code overflow="wrap" %}

```bash
npx hardhat ignition deploy ./ignition/modules/DelegationDao.js --network phron --deployment-id INSERT_YOUR_NAME
✅ Confirm deploy to network phron (7744)? … yesHardhat Ignition 🚀
Deploying [ DelegationDAOModule ]
Batch #1Executed DelegationDAOModule#DelegationDAO
[ DelegationDAOModule ] successfully deployed 🚀
Deployed Addresses
DelegationDAOModule#DelegationDAO - 0x6D895A55F5ba31e582bCEe71cae394266F240e9b
```

{% endcode %}

Congratulations, your contract is live on Phron! Save the address, as you will use it to interact with this contract instance in the next step.

### Verifying Contracts on Phron <a href="#verifying-contracts-on-moonbeam" id="verifying-contracts-on-moonbeam"></a>

In this section, we'll be verifying the contract that was just deployed on Phron. Before beginning the contract verification process, you'll need to acquire a Phronscan API Key. Note that Phron use the same Phronscan API key, whereas you'll need a distinct API key.

To verify the contract, you will run the `ignition verify` command and pass the name of your deployment you set in the prior step.

```bash
npx hardhat ignition verify INSERT_YOUR_NAME
```

> ### Note
>
> If you're deploying `DelegationDAO.sol` verbatim without any changes, you may get an `Already Verified` error because Phronscan automatically recognizes and verifies smart contracts that have matching bytecode. Your contract will still show as verified, so there is nothing else you need to do. However, if you'd prefer to verify your own `DelegationDAO.sol`, you can make a small change to the contract (such as changing a comment) and repeating the compilation, deployment, and verification steps.

In your terminal you should see the source code for your contract was successfully submitted for verification. If the verification was successful, you should see **Successfully verified contract** and there will be a link to the contract code on Phronscan. If the plugin returns an error, double check that your API key is configured correctly and that you have specified all necessary parameters in the verification command. You can refer to the guide to the Hardhat Etherscan plugin for more information.

{% code overflow="wrap" %}

```bash
npx hardhat ignition verify INSERT_YOUR_NAME
Nothing to compileSuccessfully submitted source code for contract contracts/DelegationDAO.sol:DelegationDAO at 0x6D895A55F5ba31e582bCEe71cae394266F240e9b for verification on the block explorer. Waiting for verification result...
Successfully verified contract DelegationDAO on Etherscan.
https://testnet.phronscan.io/address/0x6D895A55F5ba31e582bCEe71cae394266F240e9b#code
```

{% endcode %}

And that's it! We covered a lot of ground in this tutorial, but there's more resources available if you'd like to go deeper, including the following:

* [Hardhat guide to Testing Contracts](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)
* [Writing tasks and scripts](https://hardhat.org/hardhat-runner/docs/guides/tasks)

This tutorial is for educational purposes only. As such, any contracts or code created in this tutorial should not be used in production.The information presented herein has been provided by third parties and is made available solely for general information purposes. Phron does not endorse any project listed and described on the Phron Doc Website (<https://docs.Phron.ai/>). Phron does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Phron disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Phron. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Phron has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Phron harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.phron.ai/developers/copy/smart-contracts/writing-smart-contracts/solidity-contracts/phron-api/get-started-with-smart-contracts/hardhat-developer-workflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
