1. 토큰 전송 (transfer) 함수
2. 테스트
transfer 함수만 추가
보내는 사람의 잔고가 충분한지 확인하고,
(부족할 시 생기는 overflow를 보기 좋게 다른 오류로 보여줌)
보내는 사람 / 받는 사람 잔고를 각각 변화시켜준다
// 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) {
name = _name;
symbol = _symbol;
decimals = _decimals;
_mint(1*10**uint256(decimals), msg.sender); // 1MT
}
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;
}
}
contract를 배포할 때 Signer를 지정할 수 있음
(msg.sender의 값이 지정한 주소로 나오겠죠)
transaction VS view function
state를 보기만 하면 (view function) api call로 리턴해주고, transaction이 아님. 이 때 여러 개의 노드를 참고할 수 있다. (무결성, 탈중앙화..)
하지만 state를 초기화하거나 변경하는 건 transaction이고, 수수료를 내야한다.
추가한 함수를 test에서 사용하려면 컴파일을 해줘야 한다.
❯ npx hardhat compile
Generating typings for: 1 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 6 typings!
Compiled 1 Solidity file successfully (evm target: paris).
before에서 beforEach로 변경
각각의 테스트를 독립적으로 유지 (신경 안쓰고
"should have 0.5MT"
signer1을 가져왔고,
hre.ethers.parseUnits (또는 그냥 parseUnits)를 이용해 잔고를 확인했다.
(이전 mint 테스트에서 한 직접 숫자를 적는 형식 대신에 사용)
"should be reverted with insufficient balance error"
잔고인 0.5보다 많이 보내서 오류가 나는지 확인하는 테스트.
await의 위치 중요!
import hre from "hardhat";
import { expect } from "chai";
import { MyToken } from "../typechain-types";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { parseUnits } from "ethers";
// hardhat에서 컴파일 할 때 필요한 타입 정의 파일을 여기에 보관함
describe("mytoken deploy", () => {
let myTokenC: MyToken;
let signers: HardhatEthersSigner[];
// before > describe, let myTokenC > myTokenC 사용ok
before("should deploy", async () => {
signers = await hre.ethers.getSigners();
myTokenC = await hre.ethers.deployContract("MyToken", [
"MyToken",
"MT",
18,
]);
});
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(18);
});
it("should retrun 1MT totalSupply", async () => {
expect(await myTokenC.totalSupply()).equal(1n * 10n ** 18n);
});
// 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(1n * 10n ** 18n);
});
it("should have 0.5MT", async () => {
const signer1 = signers[1];
await myTokenC.transfer(hre.ethers.parseUnits("0.5", 18), signer1.address);
expect(await myTokenC.balanceOf(signer1.address)).equal(
hre.ethers.parseUnits("0.5", 18),
);
});
// 일부러 0.5보다 많이 보내서 오류 만들기
it("should be reverted with insufficient balance error", async () => {
const signer1 = signers[1];
// await 위치 중요!!
await expect(
myTokenC.transfer(hre.ethers.parseUnits("1.1", 18), signer1.address),
).to.be.revertedWith("insufficient balance");
});
의도한대로 전송이 잘 되고, 오류가 나는 모습도 볼 수 있다~
❯ npx hardhat test
mytoken deploy
✔ should return name (68ms)
✔ should return symbol (45ms)
✔ should return decimals
✔ should retrun 1MT totalSupply
✔ should retrun 1MT balance for signer 0
✔ should have 0.5MT
1) should return insufficient balance
6 passing (3s)
1 failing
1) mytoken deploy
should return insufficient balance:
Error: VM Exception while processing transaction: reverted with reason string 'insufficient balance'