Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 25 additions & 30 deletions extension/packages/hardhat/deploy/01_deploy_se2_token.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { deployScript, artifacts } from "../rocketh/deploy.js";

/**
* Deploys a contract named "YourContract" using the deployer account and
* constructor arguments set to the deployer address
* Deploys a contract named "SE2Token" using the deployer account.
*
* @param hre HardhatRuntimeEnvironment object.
* @param env Rocketh environment object.
*/
const deploySe2Token: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
/*
On localhost, the deployer account is the one that comes with Hardhat, which is already funded.
export default deployScript(
async env => {
/*
On localhost, the deployer account is the one that comes with Hardhat, which is already funded.

When deploying to live networks (e.g `yarn deploy --network sepolia`), the deployer account
should have sufficient balance to pay for the gas fees for contract creation.
When deploying to live networks (e.g `yarn deploy --network sepolia`), the deployer account
should have sufficient balance to pay for the gas fees for contract creation.

You can generate a random account with `yarn generate` which will fill DEPLOYER_PRIVATE_KEY
with a random private key in the .env file (then used on hardhat.config.ts)
You can run the `yarn account` command to check your balance in every network.
*/
const { deployer } = await hre.getNamedAccounts();
const { deploy } = hre.deployments;
You can generate a random account with `yarn generate` or `yarn account:import` to import your
existing PK which will fill DEPLOYER_PRIVATE_KEY_ENCRYPTED in the .env file (then used on hardhat.config.ts)
You can run the `yarn account` command to check your balance in every network.
*/
const { deployer } = env.namedAccounts;

await deploy("SE2Token", {
from: deployer,
log: true,
// autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
// automatically mining the contract deployment transaction. There is no effect on live networks.
autoMine: true,
});
};

export default deploySe2Token;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags SE2Token
deploySe2Token.tags = ["SE2Token"];
await env.deploy("SE2Token", {
account: deployer,
artifact: artifacts.SE2Token,
});
},
{
// Tags are useful if you have multiple deploy files and only want to run some of them.
// e.g. yarn deploy --tags SE2Token
tags: ["SE2Token"],
},
);
28 changes: 21 additions & 7 deletions extension/packages/hardhat/hardhat.config.ts.args.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const preContent = `
import "./tasks"
import { sayHelloTask } from "./tasks/index.js"

// Custom variables
// const CUSTOM_API_KEY = process.env.CUSTOM_API_KEY;
Expand All @@ -20,21 +20,35 @@ export const configOverrides = {
},
],
},
// In Hardhat v3, custom block explorers are declared per-chain via top-level
// `chainDescriptors` (keyed by chainId), not a per-network `verify` block.
// The Etherscan API key stays at the top level (base config's `verify.etherscan.apiKey`).
// `hardhat verify` resolves the explorer by the live network's chainId.
chainDescriptors: {
99999: {
name: "Custom Network",
blockExplorers: {
etherscan: {
name: "Custom Explorer",
url: "https://custom-explorer.io",
apiUrl: "https://api.custom-explorer.io",
},
},
},
},
networks: {
hardhat: {
forking: {
blockNumber: 1234567
}
},
customNetwork: {
type: "http",
url: "https://custom.network",
accounts: ["$$deployerPrivateKey$$"],
verify: {
etherscan: {
apiUrl: "https://api.custom-explorer.io",
apiKey: "$$etherscanApiKey$$",
}
}
chainId: 99999,
}
},
// Append the extension's task to the base `deployTasks` array.
tasks: "$$[...deployTasks, sayHelloTask]$$",
};
10 changes: 7 additions & 3 deletions extension/packages/hardhat/tasks/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { task } from "hardhat/config";

task("sayHello", "Prints 'Hello, World!'").setAction(async () => {
console.log("Hello, World!");
});
// In Hardhat 3, tasks are built and registered via the `tasks` array in
// `hardhat.config.ts`. We export the built task definition and add it there.
export const sayHelloTask = task("sayHello", "Prints 'Hello, World!'")
.setInlineAction(async () => {
console.log("Hello, World!");
})
.build();
70 changes: 29 additions & 41 deletions extension/packages/hardhat/test/SE2Token.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,57 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { SE2Token } from "../typechain-types";
import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
import { network } from "hardhat";
import type { Abi_SE2Token } from "../generated/abis/SE2Token.js";
import { loadAndExecuteDeploymentsFromFiles } from "../rocketh/environment.js";

describe("SE2Token", function () {
let token: SE2Token;
let owner: SignerWithAddress;
let user1: SignerWithAddress;
let user2: SignerWithAddress;

beforeEach(async function () {
// Get signers
[owner, user1, user2] = await ethers.getSigners();
const { provider, networkHelpers, ethers } = await network.create();

// Deploy the token
const SE2Token = await ethers.getContractFactory("SE2Token");
token = await SE2Token.deploy();
await token.waitForDeployment();
});
// We define a fixture to reuse the same setup in every test.
async function deployFixture() {
const env = await loadAndExecuteDeploymentsFromFiles({ provider });
const { address, abi } = env.get<Abi_SE2Token>("SE2Token");
const [, user1, user2] = await ethers.getSigners();
const token = await ethers.getContractAt(abi, address);
return { token, address, abi, user1, user2 };
}

describe("SE2Token", function () {
describe("Initial Setup", function () {
it("should have correct name, symbol and initial supply", async function () {
const name = await token.name();
const symbol = await token.symbol();
const supply = await token.totalSupply();
const { token } = await networkHelpers.loadFixture(deployFixture);

expect(name).to.equal("SE2Token");
expect(symbol).to.equal("SE2");
expect(supply).to.equal(0n);
expect(await token.name()).to.equal("SE2Token");
expect(await token.symbol()).to.equal("SE2");
expect(await token.totalSupply()).to.equal(0n);
});
});

describe("Minting", function () {
it("should mint tokens correctly", async function () {
const { token, user1 } = await networkHelpers.loadFixture(deployFixture);
const mintAmount = 100n * 10n ** 18n; // 100 tokens

// Mint tokens to user1
await token.connect(owner).mint(user1.address, mintAmount);

// Check balance
const balance = await token.balanceOf(user1.address);
const totalSupply = await token.totalSupply();
// Minting is open to anyone; the default signer mints to user1
await token.mint(user1.address, mintAmount);

expect(balance).to.equal(mintAmount);
expect(totalSupply).to.equal(mintAmount);
expect(await token.balanceOf(user1.address)).to.equal(mintAmount);
expect(await token.totalSupply()).to.equal(mintAmount);
});
});

describe("Transfer", function () {
it("should transfer tokens correctly", async function () {
const { address, abi, user1, user2 } = await networkHelpers.loadFixture(deployFixture);
const mintAmount = 100n * 10n ** 18n; // 100 tokens
const transferAmount = 30n * 10n ** 18n; // 30 tokens

// Mint tokens to user1
await token.connect(owner).mint(user1.address, mintAmount);

// Transfer from user1 to user2
await token.connect(user1).transfer(user2.address, transferAmount);
const tokenAsUser1 = await ethers.getContractAt(abi, address, user1);

// Check balances
const user1Balance = await token.balanceOf(user1.address);
const user2Balance = await token.balanceOf(user2.address);
// Mint to user1, then transfer user1 -> user2
await tokenAsUser1.mint(user1.address, mintAmount);
await tokenAsUser1.transfer(user2.address, transferAmount);

expect(user1Balance).to.equal(mintAmount - transferAmount);
expect(user2Balance).to.equal(transferAmount);
expect(await tokenAsUser1.balanceOf(user1.address)).to.equal(mintAmount - transferAmount);
expect(await tokenAsUser1.balanceOf(user2.address)).to.equal(transferAmount);
});
});
});
Loading