Truffle 사용하기

Truffle를 사용하여 스마트 컨트랙트를 배포하고 실행합니다.

본 장에서는 Truffle을 이용하여 스마트 컨트랙트를 작성하고 배포하는 방법에 대하여 설명합니다.

Node package manager인 npm 사용하여 Truffle을 설치할 수 있습니다. npm 설치 방법은 다음 링크를 참조하세요. https://www.npmjs.com/

$ npm install --g truffle

Truffle이 설치되었다면 truffle init 명령을 이용하여 초기화를 합니다.

$ truffle init

Starting init...
================

> Copying project files to /Users/user/Projects/Solidity/truffle-test

Init successful, sweet!

Try our scaffold commands to get started:
  $ truffle create contract YourContractName # scaffold a contract
  $ truffle create test YourTestName         # scaffold a test

http://trufflesuite.com/docs

$ tree
.
├── contracts
├── migrations
├── test
└── truffle-config.js

4 directories, 1 file

truffle init을 수행하면 Truffle project가 생성됩니다. 생성된 Truffle project는 build/contracts, contracts, migrations, test, truffle-config.js 로 구성되어 있습니다.

  • build/contracts : solidity로 작성한 contract가 compile된 결과(abi, bytecode)가 저장

  • contract : smart contract solidity files

  • migrations : deploy code(js format)

  • test : test code(js format)

  • truffle-config.js : solidity compiler version 설정, network 설정 등의 configuration

truffle create contract 명령을 이용하면 간단한 스마트 컨트랙트 템플릿을 생성합니다.

/ SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Greeter {
  constructor() public {
  }
}

이 템플릿에 앞서 작성했던 Greeter.sol를 적용해 봅니다.

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Greeter {
    string private greeting;

    constructor(string memory _greeting) public {
        greeting = _greeting;
    }

    function greet() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }
}

Greeter.sol 스마트 컨트랙트를 컴파일하고 배포하기 위하여 truffle-config.js 파일을 수정하여야 합니다.

배포를 위해 사용할 계정에 대한 설정을 위해 truflle-config.js 파일의 HDWalletProvider와 privKeys를 추가합니다. 프라이빗 키는 Web Wallet 또는 MetaMask를 통해 계정을 생성한 후 가져올 수 있습니다.

const HDWalletProvider = require('@truffle/hdwallet-provoder');
const privKeys = ["privatekey from Web Wallet"];

WEMIX3.0 테스트넷을 사용하기 위해서는 아래와 같이 네트워크 설정을 추가합니다.

networks: {
  wemix_testnet: {
    provider: ()=> new HDWalletProvider(privKeys, "https://api.test.wemix.com"),
    network_id: 1112,
    maxFeePerGas: 100000000010,
    maxPriorityFeePerGas: 100000000000
  }
},

마지막으로 사용하고자 하는 솔리디티 컴파일러 버전을 설정합니다. 현재 최신 버전은 0.8.x 이며 예제는 0.8.11 버전을 사용합니다.

컴파일러를 사용하는 운영체제에 바로 설치되어 있으면 초기 설정과 동일하게 docker 설정을 주석처리하면 되며, docker를 사용하여 설치하기 위해서는 아래와 같이 "docker: true"로 설정하고 docker가 설치되어 있어야 합니다. optimizer를 사용한다면 주석을 해제하고 적절한 설정을 해주면 됩니다.

compilers: {
    solc: {
      version: "0.8.11",    // Fetch exact version from solc-bin (default: truffle's version)
      docker: true,         // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      }
    }

truffle-config.js 파일 구성이 완성되면 스마트 컨트랙트 컴파일을 수행합니다. truffle compile <file name>을 truffle project 폴더에서 수행하면 대상으로 지정한 solidity 파일을 컴파일하게 됩니다. 컴파일된 solidity contract는 build/contracts 폴더에 <contract name>.json 포맷으로 저장됩니다.

truffle compile <file name>
ex) truffle compile Greeter.sol

컴파일된 스마트 컨트랙트를 블록체인에 배포하기 위해 다음과 같이 스크립트를 작성하고 1_deploy_contracts.js로 저장합니다.

var Greeter = artifacts.require("./Greeter.sol");

module.exports = function(deployer) {
  deployer.deploy(Greeter, "Hello!")
    .then(() => Greeter.deployed());
};

배포할 스마트 컨트랙트를 artifacts.require(<build/contracts에 저장된 artifacts file 명>)로 로드하고, deployer.deploy(contract_artifacts,{constructor arguments})를 수행하면 개별적으로 스마트 컨트랙트를 배포할 수 있습니다.

truffle migrate <file name>
ex) truffle migrate 1_deploy_contracts.js

배포 스크립트는 위의 truffle migrate <file name>으로 수행할 수 있습니다. <file name>을 사용하지 않으면 스크립트 명에 사용된 숫자 순서대로 수행됩니다.

WEMIX3.0 테스트넷에 배포한 결과는 다음과 같습니다. 배포를 위해서는 배포에 사용할 계정에 WEMIX가 있어야 합니다. Testnet Faucet에서 필요한 WEMIX를 받을 수 있습니다.

❯ truffle migrate --reset --network wemix_testnet

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.


Starting migrations...
======================
> Network name:    'wemix_testnet'
> Network id:      1112
> Block gas limit: 105000000 (0x6422c40)


1_deploy_contracts.js
=====================

   Deploying 'Greeter'
   -------------------
   > transaction hash:    0xf180dc9041ca140547b62f1a600e2ab920cfe4776d4a5590511df3051d1d09b7
   > Blocks: 0            Seconds: 0
   > contract address:    0x450F45A74b6dC7b38E25Ca84F91C6a909B2e5728
   > block number:        21511136
   > block timestamp:     1679563304
   > account:             0x1134397c2E4aE380B7D4aa446c59D07977fCeB87
   > balance:             99.933323083999672507
   > gas used:            327493 (0x4ff45)
   > gas price:           100.000000001 gwei
   > value sent:          0 ETH
   > total cost:          0.032749300000327493 ETH

   > Saving artifacts
   -------------------------------------
   > Total cost:     0.032749300000327493 ETH

Summary
=======
> Total deployments:   1
> Final cost:          0.032749300000327493 ETH

배포한 스마트 컨트랙트를 다음과 같이 javascript 파일을 이용하여 테스트를 수행할 수 있습니다.

const migration = artifacts.require("Migrations");

contract("Migration", async () => {
    describe("Migration test", async () => {
        it("setCompleted", async () => {
            const migrations = await migration.deployed();
            await migrations.setCompleted(0);
        });
    });
});
  • contract : test 대상 contract

  • describe : test case 집합

  • it : 개별 test case

truffle test <test file name>

test code 작성이 완료되면 test file을 test 폴더에 <testName.test.js> format으로 저장하고, truffle test <testName.test.js> 를 수행하면 테스트가 수행됩니다.