본문 바로가기
프로그래밍/solidity

[220713] 스마트 컨트랙트 구현하기 - 1) 트러플로 구현하기

by 한코코 2022. 7. 13.

개발환경 설치&세팅하기

// truffle 설치&세팅
$ npm init -y
$ mkdir truffle
$ cd truffle
$ npm install -g truffle
$ npx truffle init

// react를 사용하는 front 디렉토리 만들기
$ npx create-react-app front

// ganache 네트워크 실행
$ ganache-cli
// 없을경우는 설치해주자 npm install ganache-cli

 

 

메타마스크에 ganache 네트워크 생성해서 계정 불러오기

 

 

트러플로 사용할 코드 작성하기

// truffle/contracts/Counter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

contract Counter{
  uint256 private _count; //클라이언트가 수정할 수 없게 private

  // private라서 Counter변수를 반환해주는 getter를 만들어줘야한다
  function current() public view returns(uint256){
    return _count;
  }

  // 버튼을 누를때 1증가
  function increment() public {
    _count += 1;
  }

  // 버튼을 누를때 1감소
  function decrement() public {
    _count -= 1;
  }
}

 

 

트러플로 솔리디티 compile하기

build 디렉토리가 생기고 abi파일과 바이트코드가 담겨있는 json 파일들이 생긴다.

$ npx truffle compile

 

이때 자동으로

contacts 폴더 안에 Migration.sol과

migrations 폴더 안에 1_initial_migration.js가 생성되는데 나는 안 생겨서 파일을 내용을 가져왔다.

// Migration.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function Migration() public {
    owner = msg.sender;
  }

  function setCompleted(uint completed) restricted public{
    last_completed_migration = completed;
  }

  function upgrade(address new_address) restricted public{
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}
// 1_initial_migration.js
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
  deployer.deploy(Migrations);
};

 

migration으로 스마트 컨트랙트 배포하기

build/contracts 디렉토리 안에 있는 json파일을 가져오는 migration 파일을 생성하자.

  • articatcts.require("") : 솔리디티 코드를 컴파일한 json 파일 명
  • deploy : 트러플이 제공하는 배포를 위한 tool
  • deployer.deploy : 위에서 읽어온 계약 내용
// truffle/migrations/2_deploy_Counter.js
const Counter = artifacts.require("Counter");

module.exports = function (deployer) {
  deployer.deploy(Counter);
};

 

배포를 할때, migration.json이 먼저 배포되고 다음으로 다른 파일들이 배포된다.

$ npx truffle migration

// 싱글톤 인스턴스라서 update기능이 없다.
// 수정하려면 새로 배포해야한다.
$ npx truffle migration --reset

 

메타마스크를 확인하면 계정에 잔액이 줄어있는걸 확인할 수 있다.

스마트 컨트랙를 사용해서 거래를 했기때문에 사용료인 gas비를 냈기때문이다.

 

 

 

 

 

 

 

배포된 결과 보기

truffle console을 통해서 배포 및 실행상황을 체크할 수 있다.

한꺼번에 실행되는것이 아니라 한줄한줄 실행된다는 특징을 갖고있다.

$ truffle console
$ Counter

엄청나게 길고긴 코드가 나오는데 여러가지 정보가 담겨있는것을 볼 수 있다.

 

다른 여러 속성들을 한꺼번에 보고싶다면, 다음 코드를 사용하자

$ Counter.(tab 두번)

 

 

 

 

 

그러면 Counter를 배포한 결과는 어떻게 볼까?

Counter를 배포한 결과를 instance에 담고 -> 그걸 it에 담은 코드를 통해서 볼 수 있다.

$ Counter.deployed().then( (instance) => {it = instance})
$ it

출력값에서 내가 생성해 놓았던 increment와 decrement 함수를 찾을 수 있다.

 

 

 

솔리디티에서는 워낙 큰 숫자를 많이 다루다보니 그런 큰 숫자를 다루기위해서 BN( Big Number ) 객체를 사용한다.

$ it.current()

>> BN { negative: 0, words: [ 0, <1 empty item> ], length: 1, red: null }

 

 

 

만들어두었던 increment()를 사용하면 트랜잭션 내용이 출력된다.

$ it.increment()

가나슈 서버에도 트랜잭션이 발생한걸 확인할 수 있다.

트러플과 가나슈에 각각 나온 트랜잭션 해시값이 서로 같게 나오므로 서로 같은 트랜잭션이다.

 

 

 

이때 it.current()를 다시하면 결과값이 다르게 나온다.

>> BN { negative: 0, words: [ 0 <- 트랜잭션을 생성할수록 수가 점점 늘어난다.

$ it.current()

// 현재값
>> BN { negative: 0, words: [ 1, <1 empty item> ], length: 1, red: null }

// 이전값
>> BN { negative: 0, words: [ 0, <1 empty item> ], length: 1, red: null }

 

 

하지만 값을 불러오는 call()명령어는 트랜잭션을 생성하지 않으므로 수가 증가하지 않는다.

$ it.current.call()
>> BN { negative: 0, words: [ 1, <1 empty item> ], length: 1, red: null }

 

 

 

 

 

 

 

 

테스트 파일로 컨트랙트 배포, 실행상황 체크하기

 

테스트코드의 기본형

테스트 파일을 작성해서 코드가 제대로 동작하는지 테스트해본다

테스트할 코드를 it으로 시작해서 작성하고, 여러개를 한꺼번에 테스트할 경우 describe로 한꺼번에 묶는다.

// artifacts.require("솔리디티 파일을 컴파일한 json 파일명");
const Counter = artifacts.require("counter");

describe("테스트_묶음_설명글", () => {
  it("테스트_설명글", async () => {
	// 테스트 할 내용 작성
  });
});

 

 

컴파일한 counter.json을 테스트하는 테스트코드

// test/counter.test.js
const Counter = artifacts.require("counter");

describe("Counter Test", () => {
  let counter;

  it("Counter deployed", async () => {
    // counter.sol파일의 컨트랙트가 배포된 내용을 변수 counter에 저장
    counter = await Counter.deployed();
  });

  // 현재 상태를 가져오는 current.call()
  it("get current", async () => {
    console.log(await counter.current.call()); //return
  });

  it("increment", async () => {
    await counter.increment(); // eth.getTransaction(), eth.getTransactionReceipt()
    console.log(await counter.current.call()); //return
  });

  it("increment", async () => {
    await counter.increment();
    console.log(await counter.current.call()); //return
  });

  it("decrement", async () => {
    await counter.decrement();
    const result = await counter.current.call() // 이더리움 클라이언트에서 가져온 값
    console.log(result.toNumber())
  });
});

 

 

테스트 실행하기

$ truffle test

 

 

실행결과

테스트를 실행할때마다 테스트 설명 텍스트가 출력된다.

숫자를 하나 증가시키는 increment 메서드가 2번, 숫자를 하나 감소시키는 decrement 메서드가 1번 실행되었다.

0 +1 +1 -1 = 1 이므로, 1이 출력된다.

 

 

CA값 확인하기

배포시 트러플은 반환된 CA를 build/contract/해당파일.json에 업데이트를 한다.

이게 없을 경우, 배포가 잘 되지 않았다는 뜻이므로 다시 배포해야한다.

$ Counter.address

댓글