1. 지금까지 작성한 코드 테스트/확인할 때 편하도록 정리하기
constructor에서 mint함수로 토큰의 양을 입력한만큼 (_amount) 발행하도록 변경.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract MyToken {
string public name;
string public symbol;
uint8 public decimals;
//토큰의 총 발행 개수
uint256 public totalSupply;
//누가 얼마나 가지고 있는지
mapping(address => uint256) public balanceOf;
// (key => value)
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _amount) {
name = _name;
symbol = _symbol;
decimals = _decimals;
_mint(_amount *10**uint256(decimals), msg.sender); // amount만큼 MT 발행
}
function _mint(uint256 amount, address owner) internal {
totalSupply += amount;
balanceOf[owner] += amount;
}
function transfer(uint256 amount, address to) external {
require(balanceOf[msg.sender] >= amount, "insufficient balance");
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
}
}
❯ npx hardhat compile
const mintingAmount, decimals
자주 쓰이는 항목을 상수로 지정하고 사용되는 부분들을 변경함
ex). (1n 10n ** 18n) --> (mintingAmount 10n ** decimals)
describe 분할
기본적인 My Token 안에 세분화하여 describe로 묶을 수 있다.
--> 각 테스트를 항목별로 나누어 둠.
("Basic state value check", "Mint", "Transfer")
beforeEach
각각의 테스트를 독립적으로 실행하게 해준다.
이전 테스트 내용 신경쓰지 않고 테스트 가능
import hre from "hardhat";
import { expect } from "chai";
import { MyToken } from "../typechain-types";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { parseUnits } from "ethers";
// 반복되는 상수 명명
const mintingAmount = 100n;
const decimals = 18n;
describe("My Token", () => {
let myTokenC: MyToken;
let signers: HardhatEthersSigner[];
// before > describe, let myTokenC > myTokenC 사용ok
beforeEach("should deploy", async () => {
signers = await hre.ethers.getSigners();
myTokenC = await hre.ethers.deployContract("MyToken", [
"MyToken",
"MT",
decimals,
mintingAmount, //현재 100MT 발행
]);
});
describe("Basic state value check", () => {
it("should return name", async () => {
expect(await myTokenC.name()).equal("MyToken");
});
it("should return symbol", async () => {
expect(await myTokenC.symbol()).equal("MT");
});
it("should return decimals", async () => {
expect(await myTokenC.decimals()).equal(decimals);
});
it("should retrun 100 totalSupply", async () => {
expect(await myTokenC.totalSupply()).equal(
mintingAmount * 10n ** decimals,
);
});
});
describe("Mint", () => {
// 1MT = 1*(10^18) = 1n*10n**18n = BigInt(1*10**18)
it("should retrun 1MT balance for signer 0", async () => {
expect(await myTokenC.balanceOf(signers[0].address)).equal(
mintingAmount * 10n ** decimals,
);
});
});
describe("Transfer", () => {
it("should have 0.5MT", async () => {
const signer1 = signers[1];
await myTokenC.transfer(
hre.ethers.parseUnits("0.5", decimals),
signer1.address,
);
expect(await myTokenC.balanceOf(signer1.address)).equal(
hre.ethers.parseUnits("0.5", decimals),
);
});
it("should be reverted with insufficient balance error", async () => {
const signer1 = signers[1];
await expect(
myTokenC.transfer(
hre.ethers.parseUnits((mintingAmount + 1n).toString(), decimals),
signer1.address,
),
).to.be.revertedWith("insufficient balance");
});
});
});
❯ npx hardhat test
Mytoken
Basic state value check
✔ should return name (105ms)
✔ should return symbol
✔ should return decimals
✔ should retrun 100 totalSupply
Mint
✔ should retrun 1MT balance for signer 0
Transfer
✔ should have 0.5MT
✔ should be reverted with insufficient balance error (87ms)
7 passing (5s)
이렇게 기능별로 테스트 결과를 확인하기도 더 편리하다.
❯ git add contracts/MyToken.sol
❯ git commit -m "added transfer"
❯ git add .
❯ git commit -m "transfer test"