Last active
October 10, 2024 12:18
-
-
Save veektrie/8f0fcf2567e0365a19be2f287e2ba536 to your computer and use it in GitHub Desktop.
Learn how to use Hardhat for a more advanced Solidity development workflow.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://hardhat.org/hardhat-runner/docs/getting-started#installation | |
https://nodejs.org/en | |
Installation & Setup | |
A. Prerequisites: | |
- Node.js and npm: Ensure you have [Node.js](https://nodejs.org/) (which includes npm) installed. Verify installation by running: | |
```bash | |
node -v | |
npm -v | |
``` | |
B. Setting Up a New Hardhat Project: | |
1. Create a Project Directory: | |
```bash | |
mkdir hardhat-demo | |
cd hardhat-demo | |
``` | |
2. Initialize a New npm Project: | |
```bash | |
npm init -y | |
``` | |
- Explanation: This command creates a `package.json` file with default settings, managing project dependencies. | |
3. Install Hardhat: | |
```bash | |
npm install --save-dev hardhat | |
``` | |
- Explanation: Installs Hardhat as a development dependency. | |
4. Initialize Hardhat: | |
```bash | |
npx hardhat | |
``` | |
- Interactive Setup: | |
- Choose a Task: Select "Create a basic sample project". | |
- Project Directory: Confirm the current directory. | |
- Add .gitignore: Yes, to ignore `node_modules` and other unnecessary files. | |
- Install Sample Project Dependencies: Agree to install them automatically. | |
- Result: Hardhat sets up a sample project with the following structure: | |
``` | |
hardhat-demo/ | |
├── contracts/ | |
│ └── Greeter.sol | |
├── scripts/ | |
│ └── sample-script.js | |
├── test/ | |
│ └── sample-test.js | |
├── hardhat.config.js | |
├── package.json | |
└── .gitignore | |
``` | |
C. Understanding the Folder Structure: | |
- `contracts/`: Contains Solidity contracts. | |
- `scripts/`: JavaScript scripts for deploying contracts. | |
- `test/`: Contains test scripts for smart contracts. | |
- `hardhat.config.js`: Configuration file for Hardhat settings and plugins. | |
- `package.json`: Manages project dependencies and scripts. | |
- `.gitignore`: Specifies files and directories to ignore in version control. | |
3. Creating a Contract: ERC20 Token | |
A. Overview of ERC20 Tokens: | |
ERC20 is a standard interface for fungible tokens on Ethereum, defining functions like `transfer`, `balanceOf`, and `approve`. Implementing an ERC20 token ensures compatibility with wallets, exchanges, and other smart contracts. | |
B. Creating the ERC20 Contract: | |
1. Navigate to the `contracts` Directory: | |
```bash | |
cd contracts | |
``` | |
2. Create a New File Named `MyToken.sol`: | |
```bash | |
touch MyToken.sol | |
``` | |
3. Write the ERC20 Contract: | |
Open `MyToken.sol` in your preferred code editor and add the following code: | |
```solidity | |
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | |
contract MyToken is ERC20 { | |
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) { | |
_mint(msg.sender, initialSupply (10 decimals())); | |
} | |
function mint(address to, uint256 amount) public { | |
_mint(to, amount); | |
} | |
function burn(address from, uint256 amount) public { | |
_burn(from, amount); | |
} | |
} | |
``` | |
Explanation: | |
- SPDX License Identifier: Specifies the MIT license. | |
- Pragma Directive: Uses Solidity version `^0.8.0`. | |
- Import Statement: Imports the ERC20 implementation from OpenZeppelin. | |
- Contract `MyToken`: | |
- Constructor: Initializes the token with a name, symbol, and initial supply, minting the initial supply to the deployer’s address. | |
- `mint` Function: Allows minting new tokens to a specified address. | |
- `burn` Function: Allows burning tokens from a specified address. | |
4. Install OpenZeppelin Contracts: | |
To use OpenZeppelin's ERC20 implementation, install the package: | |
```bash | |
npm install @openzeppelin/contracts | |
``` | |
- Explanation: This installs the OpenZeppelin Contracts library, providing secure and community-vetted implementations of ERC20 and other standards. | |
4. Compilation & Local Node | |
A. Compiling the Contract: | |
1. Navigate Back to the Project Root: | |
```bash | |
cd .. | |
``` | |
2. Compile the Contracts: | |
```bash | |
npx hardhat compile | |
``` | |
- Output: | |
- Hardhat compiles the Solidity contracts, generating artifacts in the `artifacts/` and `cache/` directories. | |
- If there are compilation errors, they will be displayed in the console. Address any issues before proceeding. | |
B. Spinning Up a Local Hardhat Node: | |
1. Start the Hardhat Local Node: | |
```bash | |
npx hardhat node | |
``` | |
- Explanation: This command starts a local Ethereum network with predefined accounts and instant mining, ideal for development and testing. | |
- Output: | |
- Provides a list of accounts with private keys and the network’s RPC URL (usually `http://127.0.0.1:8545/`). | |
Note: Keep this terminal window open as it runs the local node. Open a new terminal window for deploying contracts and running scripts. | |
5. Deploying to a Local Node | |
A. Writing a Deployment Script: | |
1. Navigate to the `scripts` Directory: | |
```bash | |
cd scripts | |
``` | |
2. Create a Deployment Script Named `deploy.js`: | |
```bash | |
touch deploy.js | |
``` | |
3. Write the Deployment Script: | |
Open `deploy.js` in your code editor and add the following code: | |
```javascript | |
const hre = require("hardhat"); | |
async function main() { | |
// Fetch the contract to deploy | |
const MyToken = await hre.ethers.getContractFactory("MyToken"); | |
// Define token parameters | |
const name = "My Custom Token"; | |
const symbol = "MCT"; | |
const initialSupply = 1000; | |
// Deploy the contract | |
const myToken = await MyToken.deploy(name, symbol, initialSupply); | |
await myToken.deployed(); | |
console.log("MyToken deployed to:", myToken.address); | |
} | |
// Handle errors and run the main function | |
main() | |
.then(() => process.exit(0)) | |
.catch((error) => { | |
console.error(error); | |
process.exit(1); | |
}); | |
``` | |
Explanation: | |
- Import Hardhat Runtime Environment (HRE): Provides access to Hardhat's functionalities. | |
- `main` Function: | |
- `getContractFactory`: Prepares the contract for deployment. | |
- Define Token Parameters: Sets the token’s name, symbol, and initial supply. | |
- Deploy the Contract: Deploys `MyToken` with the specified parameters. | |
- Log the Deployed Address: Outputs the contract address upon successful deployment. | |
- Error Handling: Catches and logs any errors during deployment. | |
B. Deploying the Contract: | |
1. Ensure the Local Node is Running: | |
- Confirm that the Hardhat node is active in another terminal window. | |
2. Deploy the Contract to the Local Node: | |
```bash | |
npx hardhat run scripts/deploy.js --network localhost | |
``` | |
- Explanation: This command runs the `deploy.js` script on the `localhost` network (the Hardhat node). | |
- Output: | |
``` | |
MyToken deployed to: 0xYourContractAddress | |
``` | |
- Note: Replace `0xYourContractAddress` with the actual deployed contract address displayed. | |
C. Understanding Deployment Artifacts: | |
- Artifacts: Located in the `artifacts/` directory, containing the compiled contract's ABI and bytecode. | |
- Deployment Addresses: Important for interacting with the deployed contracts. | |
6. Console Interaction | |
A. Using the Hardhat Console: | |
1. Open a New Terminal Window: | |
- Keep the Hardhat node running in its terminal. | |
2. Access the Hardhat Console: | |
```bash | |
npx hardhat console --network localhost | |
``` | |
- Explanation: Launches an interactive JavaScript console connected to the local Hardhat network. | |
3. Interact with the Deployed Contract: | |
i. Fetch the Deployed Contract Instance: | |
```javascript | |
const MyToken = await ethers.getContractFactory("MyToken"); | |
const myToken = await MyToken.attach("0xYourContractAddress"); | |
``` | |
- Replace `"0xYourContractAddress"` with the actual contract address obtained during deployment. | |
ii. View Token Details: | |
```javascript | |
const name = await myToken.name(); | |
console.log("Token Name:", name); // Outputs: My Custom Token | |
const symbol = await myToken.symbol(); | |
console.log("Token Symbol:", symbol); // Outputs: MCT | |
const totalSupply = await myToken.totalSupply(); | |
console.log("Total Supply:", totalSupply.toString()); // Outputs: 1000000000000000000000 (considering decimals) | |
``` | |
iii. Check Account Balance: | |
```javascript | |
const [owner] = await ethers.getSigners(); | |
const balance = await myToken.balanceOf(owner.address); | |
console.log("Owner Balance:", balance.toString()); // Outputs: 1000000000000000000000 | |
``` | |
iv. Mint New Tokens: | |
```javascript | |
await myToken.mint("0xRecipientAddress", 500); | |
const newBalance = await myToken.balanceOf("0xRecipientAddress"); | |
console.log("Recipient Balance:", newBalance.toString()); // Outputs: 500000000000000000000 | |
``` | |
- Note: Replace `"0xRecipientAddress"` with a valid address from the local Hardhat node. | |
v. Burn Tokens: | |
```javascript | |
await myToken.burn(owner.address, 200); | |
const updatedBalance = await myToken.balanceOf(owner.address); | |
console.log("Updated Owner Balance:", updatedBalance.toString()); // Outputs: 999800000000000000000 | |
``` | |
B. Using the Console for Advanced Interactions: | |
- Transferring Ownership (if implemented): | |
```javascript | |
await myToken.transferOwnership("0xNewOwnerAddress"); | |
const newOwner = await myToken.owner(); | |
console.log("New Owner:", newOwner); | |
``` | |
- Listing All Token Holders: | |
- Note: Requires maintaining a list of holders within the contract or using events. | |
C. Exiting the Console: | |
- Type `.exit` or press `Ctrl + D` to exit the Hardhat console. | |
7. Debugging Tools | |
A. Introduction to Hardhat’s Debugging Capabilities: | |
Hardhat provides robust debugging tools that help developers identify and resolve issues within smart contracts. These tools include detailed error messages, stack traces, and the ability to inspect the execution flow of transactions. | |
B. Common Debugging Scenarios: | |
1. Reverted Transactions: | |
- Occur when a `require`, `revert`, or `assert` statement fails. | |
- Example: Attempting to mint tokens to an invalid address. | |
2. Gas Limit Exceeded: | |
- Happens when a transaction runs out of gas. | |
- Example: Deploying a contract with excessive computational requirements. | |
3. Unexpected State Changes: | |
- Occurs when contract state does not change as intended. | |
- Example: Incorrectly updating a state variable. | |
C. Using Hardhat’s Built-In Debugger: | |
1. Trigger an Error: | |
- Modify the `mint` function to include a condition that can fail. | |
```solidity | |
function mint(address to, uint256 amount) public { | |
require(to != address(0), "Cannot mint to the zero address"); | |
_mint(to, amount); | |
} | |
``` | |
2. Recompile the Contract: | |
```bash | |
npx hardhat compile | |
``` | |
3. Redeploy the Contract: | |
- Update the deployment script if necessary and redeploy using: | |
```bash | |
npx hardhat run scripts/deploy.js --network localhost | |
``` | |
4. Attempt to Mint to the Zero Address: | |
- Use the Hardhat console or a script to call `mint` with `0x0000000000000000000000000000000000000000`. | |
```javascript | |
await myToken.mint("0x0000000000000000000000000000000000000000", 100); | |
``` | |
- Result: Transaction reverts with the error message "Cannot mint to the zero address". | |
5. Debug the Failed Transaction: | |
- Using Console Logs: | |
- The error message is displayed, indicating where the transaction failed. | |
- Using Hardhat’s Trace Feature: | |
- Unfortunately, Hardhat doesn’t have a built-in step-through debugger like Remix. However, you can use plugins or integrate with other debugging tools. | |
- Using Hardhat's `debug` Task: | |
- Start the Hardhat node with debugging enabled. | |
```bash | |
npx hardhat node --logging | |
``` | |
- Note: This provides more detailed logs that can help trace issues. | |
- Leveraging Stack Traces: | |
- When a transaction fails, Hardhat provides stack traces pointing to the exact line in the Solidity code where the error occurred. | |
6. Analyzing the Error: | |
- Identify that the `require` statement in the `mint` function failed due to an attempt to mint to the zero address. | |
7. Fixing the Issue: | |
- Ensure that the `to` address is valid before calling the `mint` function. | |
- Implement additional checks or handle exceptions gracefully. | |
D. Best Practices for Debugging: | |
1. Use Descriptive Error Messages: | |
- Always provide clear and descriptive messages in `require`, `revert`, and `assert` statements to simplify debugging. | |
2. Emit Events: | |
- Emit events for significant state changes and actions within your contract. This aids in tracking contract behavior during interactions. | |
```solidity | |
event Minted(address indexed to, uint256 amount); | |
event Burned(address indexed from, uint256 amount); | |
function mint(address to, uint256 amount) public { | |
require(to != address(0), "Cannot mint to the zero address"); | |
_mint(to, amount); | |
emit Minted(to, amount); | |
} | |
function burn(address from, uint256 amount) public { | |
_burn(from, amount); | |
emit Burned(from, amount); | |
} | |
``` | |
3. Write Comprehensive Tests: | |
- Utilize Hardhat’s testing framework to write unit and integration tests, catching issues before deployment. | |
4. Leverage Static Analysis Tools: | |
- Use tools like `solhint` or `eslint-plugin-solidity` to analyze code for potential vulnerabilities and best practice adherence. | |
5. Review Gas Consumption: | |
- Optimize functions to reduce gas usage, preventing out-of-gas errors during deployment or execution. | |
8. Hands-On Exercise | |
Objective: Apply the knowledge gained from the demo by creating, setting up, compiling, deploying, and interacting with a custom smart contract using Hardhat. Modify the deployment script to add different parameters or deploy multiple contracts. | |
Exercise Steps: | |
1. Set Up Your Hardhat Project: | |
A. Initialize the Project: | |
- If not already done, create and navigate to a new project directory. | |
```bash | |
mkdir hardhat-exercise | |
cd hardhat-exercise | |
npm init -y | |
npm install --save-dev hardhat | |
npx hardhat | |
``` | |
- Choose "Create a basic sample project" and follow the prompts. | |
B. Install OpenZeppelin Contracts: | |
```bash | |
npm install @openzeppelin/contracts | |
``` | |
2. Write a Custom Smart Contract: | |
A. Create a New Contract File: | |
```bash | |
cd contracts | |
touch SimpleStorage.sol | |
``` | |
B. Implement the `SimpleStorage` Contract: | |
Open `SimpleStorage.sol` in your code editor and add: | |
```solidity | |
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
contract SimpleStorage { | |
uint256 private data; | |
event DataUpdated(uint256 newData); | |
constructor(uint256 initialData) { | |
data = initialData; | |
emit DataUpdated(initialData); | |
} | |
function setData(uint256 newData) public { | |
data = newData; | |
emit DataUpdated(newData); | |
} | |
function getData() public view returns (uint256) { | |
return data; | |
} | |
} | |
``` | |
Explanation: | |
- State Variable: `data` stores an unsigned integer. | |
- Event: `DataUpdated` emitted whenever `data` is updated. | |
- Constructor: Initializes `data` with `initialData`. | |
- Functions: | |
- `setData`: Updates `data` and emits an event. | |
- `getData`: Retrieves the current value of `data`. | |
3. Compile the Contract: | |
```bash | |
cd .. | |
npx hardhat compile | |
``` | |
- Ensure there are no compilation errors. Address any if present. | |
4. Deploy the Contract to a Local Node: | |
A. Start the Local Hardhat Node: | |
```bash | |
npx hardhat node | |
``` | |
B. Open a New Terminal Window and Navigate to the Project Directory. | |
C. Write a Deployment Script: | |
1. Navigate to `scripts`: | |
```bash | |
cd scripts | |
``` | |
2. Create `deploySimpleStorage.js`: | |
```bash | |
touch deploySimpleStorage.js | |
``` | |
3. Implement the Deployment Script: | |
Open `deploySimpleStorage.js` and add: | |
```javascript | |
const hre = require("hardhat"); | |
async function main() { | |
const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage"); | |
const initialData = 42; // Example initial data | |
const simpleStorage = await SimpleStorage.deploy(initialData); | |
await simpleStorage.deployed(); | |
console.log("SimpleStorage deployed to:", simpleStorage.address); | |
} | |
main() | |
.then(() => process.exit(0)) | |
.catch((error) => { | |
console.error(error); | |
process.exit(1); | |
}); | |
``` | |
Explanation: | |
- Defines `initialData` as `42` to initialize the contract. | |
- Deploys `SimpleStorage` with the specified `initialData`. | |
- Logs the deployed contract address. | |
D. Deploy the Contract: | |
```bash | |
npx hardhat run scripts/deploySimpleStorage.js --network localhost | |
``` | |
- Output: | |
``` | |
SimpleStorage deployed to: 0xYourContractAddress | |
``` | |
5. Interact with the Deployed Contract: | |
A. Open the Hardhat Console: | |
```bash | |
npx hardhat console --network localhost | |
``` | |
B. Fetch the Contract Instance: | |
```javascript | |
const SimpleStorage = await ethers.getContractFactory("SimpleStorage"); | |
const simpleStorage = await SimpleStorage.attach("0xYourContractAddress"); | |
``` | |
- Replace `"0xYourContractAddress"` with the actual address from deployment. | |
C. Retrieve Initial Data: | |
```javascript | |
const initial = await simpleStorage.getData(); | |
console.log("Initial Data:", initial.toString()); // Outputs: 42 | |
``` | |
D. Update the Data: | |
```javascript | |
const tx = await simpleStorage.setData(100); | |
await tx.wait(); | |
const updated = await simpleStorage.getData(); | |
console.log("Updated Data:", updated.toString()); // Outputs: 100 | |
``` | |
E. View Event Logs: | |
```javascript | |
// Fetch past events | |
const events = await simpleStorage.queryFilter("DataUpdated"); | |
events.forEach((event) => { | |
console.log(`Data Updated to: ${event.args.newData}`); | |
}); | |
``` | |
- Output: | |
``` | |
Data Updated to: 42 | |
Data Updated to: 100 | |
``` | |
6. Modify the Deployment Script to Add Different Parameters or Deploy Multiple Contracts: | |
A. Deploying Multiple Instances: | |
1. Update `deploy.js`: | |
Open `deploy.js` and modify it to deploy both `MyToken` and `SimpleStorage` contracts. | |
```javascript | |
const hre = require("hardhat"); | |
async function main() { | |
// Deploy MyToken | |
const MyToken = await hre.ethers.getContractFactory("MyToken"); | |
const name = "My Custom Token"; | |
const symbol = "MCT"; | |
const initialSupply = 1000; | |
const myToken = await MyToken.deploy(name, symbol, initialSupply); | |
await myToken.deployed(); | |
console.log("MyToken deployed to:", myToken.address); | |
// Deploy SimpleStorage | |
const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage"); | |
const initialData = 2024; | |
const simpleStorage = await SimpleStorage.deploy(initialData); | |
await simpleStorage.deployed(); | |
console.log("SimpleStorage deployed to:", simpleStorage.address); | |
} | |
main() | |
.then(() => process.exit(0)) | |
.catch((error) => { | |
console.error(error); | |
process.exit(1); | |
}); | |
``` | |
2. Run the Updated Deployment Script: | |
```bash | |
npx hardhat run scripts/deploy.js --network localhost | |
``` | |
- Output: | |
``` | |
MyToken deployed to: 0xTokenContractAddress | |
SimpleStorage deployed to: 0xSimpleStorageContractAddress | |
``` | |
B. Adding Deployment Parameters: | |
- Example: Deploy `MyToken` with a different initial supply. | |
1. Modify the Deployment Script: | |
```javascript | |
// Inside the main function after deploying MyToken | |
const newInitialSupply = 5000; | |
const myToken2 = await MyToken.deploy(name, symbol, newInitialSupply); | |
await myToken2.deployed(); | |
console.log("MyToken2 deployed to:", myToken2.address); | |
``` | |
2. Deploy with Additional Parameters: | |
```bash | |
npx hardhat run scripts/deploy.js --network localhost | |
``` | |
- Output: | |
``` | |
MyToken deployed to: 0xToken1Address | |
SimpleStorage deployed to: 0xStorage1Address | |
MyToken2 deployed to: 0xToken2Address | |
``` | |
C. Automating Multiple Deployments: | |
- Use Arrays or Loops to Deploy Multiple Contracts with Different Parameters. | |
```javascript | |
async function main() { | |
const contractsToDeploy = [ | |
{ | |
name: "MyToken1", | |
symbol: "MCT1", | |
initialSupply: 1000, | |
}, | |
{ | |
name: "MyToken2", | |
symbol: "MCT2", | |
initialSupply: 5000, | |
}, | |
]; | |
for (const contract of contractsToDeploy) { | |
const MyToken = await hre.ethers.getContractFactory("MyToken"); | |
const myToken = await MyToken.deploy(contract.name, contract.symbol, contract.initialSupply); | |
await myToken.deployed(); | |
console.log(`${contract.name} deployed to:`, myToken.address); | |
} | |
// Similarly, deploy multiple SimpleStorage contracts | |
const storageContracts = [100, 200, 300]; | |
for (const initialData of storageContracts) { | |
const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage"); | |
const simpleStorage = await SimpleStorage.deploy(initialData); | |
await simpleStorage.deployed(); | |
console.log(`SimpleStorage with initialData ${initialData} deployed to:`, simpleStorage.address); | |
} | |
} | |
``` | |
- Deploy All Contracts: | |
```bash | |
npx hardhat run scripts/deploy.js --network localhost | |
``` | |
7. Submitting the Exercise: | |
A. Contract Code: | |
- Submit the Solidity code of the custom `SimpleStorage` (and any additional contracts if implemented). | |
B. Deployment Screenshot: | |
- Provide a screenshot of the terminal showing the deployed contract addresses. | |
C. Interaction Logs: | |
- Document interactions performed via the Hardhat console, including function calls and their outputs. | |
D. Debugging Evidence: | |
- Include screenshots or descriptions of any debugging sessions, especially if issues were encountered and resolved. | |
E. Reflection: | |
- Write a brief summary outlining what was learned during the exercise, challenges faced, and how they were overcome. | |
Example Reflection: | |
> During this exercise, I learned how to set up a Hardhat project from scratch, write and compile Solidity contracts, and deploy them to a local Hardhat node. Interacting with the deployed contracts through the Hardhat console provided hands-on experience in managing contract states and functions. Modifying the deployment script to deploy multiple contracts reinforced my understanding of scripting and automation in Hardhat. Encountering and resolving a reverted transaction taught me the importance of thorough error handling and effective debugging strategies. | |
Tips and Best Practices | |
1. Leverage TypeScript (Optional): | |
- Hardhat supports TypeScript for enhanced type safety. Consider setting up a TypeScript environment for larger projects. | |
2. Use Environment Variables: | |
- Manage sensitive data like private keys and API URLs using environment variables with packages like `dotenv`. | |
- Example: | |
```bash | |
npm install dotenv | |
``` | |
- In `hardhat.config.js`: | |
```javascript | |
require("dotenv").config(); | |
module.exports = { | |
networks: { | |
localhost: { | |
url: "http://127.0.0.1:8545/" | |
}, | |
mainnet: { | |
url: process.env.MAINNET_URL, | |
accounts: [process.env.PRIVATE_KEY], | |
}, | |
// Additional networks | |
}, | |
solidity: "0.8.0", | |
}; | |
``` | |
3. Integrate Plugins: | |
- Enhance Hardhat’s functionality with plugins like: | |
- `hardhat-ethers`: Integration with Ethers.js. | |
- `hardhat-waffle`: Testing framework using Waffle. | |
- `hardhat-gas-reporter`: Gas usage reporting. | |
- Installation Example: | |
```bash | |
npm install --save-dev @nomiclabs/hardhat-ethers ethers | |
``` | |
4. Write Comprehensive Tests: | |
- Utilize Hardhat’s testing framework with Mocha and Chai to write unit and integration tests, ensuring contract reliability. | |
Example Test (`test/SimpleStorage.test.js`): | |
```javascript | |
const { expect } = require("chai"); | |
describe("SimpleStorage Contract", function () { | |
let SimpleStorage, simpleStorage; | |
beforeEach(async function () { | |
SimpleStorage = await ethers.getContractFactory("SimpleStorage"); | |
simpleStorage = await SimpleStorage.deploy(50); | |
await simpleStorage.deployed(); | |
}); | |
it("Should return the initial data", async function () { | |
expect(await simpleStorage.getData()).to.equal(50); | |
}); | |
it("Should update data correctly", async function () { | |
await simpleStorage.setData(100); | |
expect(await simpleStorage.getData()).to.equal(100); | |
}); | |
it("Should emit DataUpdated event on setData", async function () { | |
await expect(simpleStorage.setData(200)) | |
.to.emit(simpleStorage, "DataUpdated") | |
.withArgs(200); | |
}); | |
}); | |
``` | |
- Run Tests: | |
```bash | |
npx hardhat test | |
``` | |
5. Optimize Gas Usage: | |
- Analyze and optimize contract functions to reduce gas consumption, making transactions cost-effective. | |
6. Stay Updated with Hardhat Releases: | |
- Regularly update Hardhat and its plugins to benefit from the latest features and security patches. | |
```bash | |
npm update hardhat | |
``` | |
7. Secure Your Contracts: | |
- Follow best security practices, such as using OpenZeppelin libraries, implementing access controls, and conducting thorough audits. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment