# 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 로 구성되어 있습니다.&#x20;

* 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&#x20;

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](https://wallet.test.wemix.com) 또는 MetaMask를 통해 계정을 생성한 후 가져올 수 있습니다.&#x20;

```
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 버전을 사용합니다.&#x20;

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

```
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 포맷으로 저장됩니다.&#x20;

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

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

```
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})를 수행하면 개별적으로 스마트 컨트랙트를 배포할 수 있습니다.&#x20;

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

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

WEMIX3.0 테스트넷에 배포한 결과는 다음과 같습니다. 배포를 위해서는 배포에 사용할 계정에 WEMIX가 있어야 합니다. [Testnet Faucet](https://wallet.test.wemix.com/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 파일을 이용하여 테스트를 수행할 수 있습니다.&#x20;

```
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> 를 수행하면 테스트가 수행됩니다. &#x20;
