solidity를 이용해 smart contract를 개발 하는 방법으로 크게 remix ide를 이용하는 방법과 truffle과 ganache를 이용해 개발하는 방식이 있다.
contract의 코드가 많아지고, 테스트 코드를 통해 코드가 원하는대로 동작하는지 테스트코드를 작성하기에는 truffle과 ganache를 이용하는 것이 좀더 효율적일 수도 있다.
truffle은 개발 편의성을 위해 solidity contract의 컴파일, 테스트, 배포를 지원하는 개발환경이다. ganache는 ethereum local network 환경을 제공하는 도구로 추가적인 설정 없이 바로 테스트 네트워크를 사용할 수 있다.
먼저 truffle과 ganache를 설치해야 한다.
truffle 설치
npm install -g truffle
ganache-cli 설치
npm install -g ganache-cli
truffle를 이용해 프로젝트 생성
mkdir my-project
cd my-project
truffle init
npm init
openzeppelin 설치하기
npm install @openzeppelin/contracts
token 컨트랙트 작성
// ./contract/myToken.sol
pragma solidity ^0.5.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
contract myToken is ERC20, ERC20Detailed {
constructor(string memory _name, string memory _symbol, uint8 _decimals)
ERC20Detailed(_name, _symbol, _decimals) public {
}
}
truffle을 이용한 빌드
truffle compile
마이그레이션(배포) 설정
// 1_initial_migration.js 파일 수정
const myToken = artifacts.require("myToken");
module.exports = function (deployer) {
const _name = "My Token";
const _symbol = "TKN";
const _decimals = 18;
deployer.deploy(myToken, _name, _symbol, _decimals);
};
truffle 실행
ganache-cli
로컬 테스트넷 설정
// truffle-config.js 파일 수정
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
}
배포하기
truffle migrate
truffle의 테스트 코드는 nodejs 테스트 프레임워크인 chai를 이용해 테스트 코드를 작성할 수 있다.
다음과 같이 기본적인 token을 배포하고 배포한 token의 정보를 확인하는 테스트코드를 작성할 수 있다.
// ./test/myToken.js 파일 작성
const { BN } = require("@openzeppelin/test-helpers");
var chai = require("chai"),
expect = chai.expect,
should = chai.should();
const myToken = artifacts.require("myToken");
contract("myToken", async (accounts) => {
const _name = "My Token";
const _symbol = "TKN";
const _decimals = 18;
const _initialBalance = new BN(100000 * 10 ** _decimals);
beforeEach(async () => {
token = await myToken.new(_name, _symbol, _decimals, _initialBalance);
});
describe("creation", () => {
it("초기 발행량 확인", async () => {
const balance = await token.balanceOf.call(accounts[0]);
balance.should.be.bignumber.equal(_initialBalance);
});
it("토큰 발행 정보 확인", async () => {
const name = await token.name.call();
assert.strictEqual(name, _name);
const symbol = await token.symbol.call();
assert.strictEqual(symbol, _symbol);
const decimals = await token.decimals.call();
assert.strictEqual(decimals.toNumber(), _decimals);
});
});
});