본문 바로가기
경일/Block-chain

[block-chain / 블록체인] Solidity(솔리디티)작성 과 contract(스마트컨트랙트) 배포

by dev_kong 2022. 7. 11.
728x90
728x90

0. 목차

1. 개요

2. Solidity

3. contract 배포

1. 개요

오늘은 솔리디티 코드를 작성하고, 작성한 코드를 최근 진행한 토이프로젝트를 이용해 contract 배포를 진행 해보려 한다.

 

2. Solidity

solidity는 오로지 smart contract 작성을 위해서 존재하는 언어이다.

파일 확장자로는 .sol을 사용한다.

코드를 작성하는데 기존의 vscode에서 작업하던 것과 달리 코드에 색이 입혀지지 않는다면, solidity확장자를 설치해보자.

 

2-1. Solidity 작성

solidity 문서 최상단에는 항상 버전을 적어주는 것으로 시작한다.

 

pragma solidity ^0.8.15;

 

그리고 contract라는 예약어를 사용해서 코드를 작성한다.

js의 class 와 비슷하다.

 

pragma solidity ^0.8.15;

contract HelloWorld{
  string text;

  constructor(){
    text = "Hello World";
  }
}

 

변수는 이렇게 설정할 수 있다.

함수의 선언은 아래와 같다.

 

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

contract HelloWorld{
  string text;

  constructor(){
    text = "Hello World";
  }

  function getText() public view returns(string memory){
    return text;
  }
}

 

2-2. Compile

 

npm init -y
npm i -g solc
npx solc --bin --abi [파일 경로] 

 

명령어를 모두 실행하면 두가지의 파일이 나오는데

그중, .bin 파일이 2진수로 컴파일 된 코드이다.

 

3. Transaction(smart contract 배포)

 

컴파일된 solidity코드는 transaction의 data에 들어간다.

우선 geth를 실행해야 한다.

간단한 토이 프로젝트를 통해 구현해놓은 프라이빗 네트워크와 익스플로러가 있으니 그걸 사용하겠다.

 

geth --datadir node --http --http.addr "0.0.0.0" --http.port 9000 --http.corsdomain "" --http.api "admin,eth,debug,miner,net,txpool,personal,web3" --syncmode full --networkid 7722 --port 30300 --ws --ws.addr "0.0.0.0" --ws.port 9005 --ws.origins "" --ws.api "miner,eth,net,web3" --allow-insecure-unlock --unlock "0,1"  --password "./node/password"

 

geth를 실행시키는 명령어다.
password라는 파일을 하나 만들어서 비밀번호를 입력하고 기본적으로 걸려있는 계정의 lock을 풀어주자.

 

geth attach http://127.0.0.1:9000

 

위 명령어를 통해 geth console 에 접속할 수 있다.

편의를 위해 우선 geth console에 .bin 파일의 내용과 .abi 파일을 저장해두자
compile 을 통해 나온 파일의 내용을 복붙 하면 된다

 

> bytecode = "0x[.bin 파일 내용]"
> abi = [abi 파일 내용]

 

그리고 트랜잭션 객체도 memory에 저장해두면 편할 것같다.

 

> txObject = {from:eth.coinbase, data:bytecode}

 

이제 트랜잭션을 발생시켜보자

 

> eth.sendTransaction(txObject)
"[transaction hash]"
> txpool

 

txpool의 내용을 확인해보면 발생시킨 트랜잭션이 담겨 있는 것을 확인해볼 수 있다.

그리고 트랜잭션 해시를 잘 보관하고 있자.

 

이제 마이닝을 해보자

 

마이닝을 해야 txpool에 있는 내용이

블록에 담기면서 배포가 완료된다.

> miner.start(4)
> miner.stop()

 

블록이 마이닝 되었다면,

 

> eth.getTransaction("[transaction hash]")
> eth.getTransactionReceipt("[transaction hash]")

 

위 명령어를 통해 트랜잭션을 확인 할 수 있다.

그리고

아래의 명령어를 실행했을때 나오는 객체의 프로퍼티중 contractAddress 가

저-번 포스팅에서 얘기했던 CA 이다.

 

잘 복사해두자

 

> contract = eth.contract(abi)
> instance = contract.at('[CA]')
> instance.getText.call()
"Hello World"

 

위의 세 가지 명령어를 순차적으로 실행시키면

우리가 맨 처음 작성했던 hello world가 찍히는 걸 확인할 수 있다.

이 세가지 명령어가 제법 내용이 난해하다 하나씩 풀어보자.

 

eth.contract(abi)

이 명령어는 eth객체에 abi라는 프로퍼티를 추가하겠다는 내용이다.

abi파일 내부에는 우리가 작성한 solidity 문서의 getText라는 메서드가 들어가있다.

abi가 추가된 객체의 이름을 contract로 정해준다.

 

contract.at('[CA]')

contract 객체가 가지고 있는 transaction들중 ca가 일치하는 것을 찾아서 insatance 라는 변수에 담아준다.

 

instance.getText.call()

instance 내에 getText라는 메서드를 실행하는 코드이다.

getText는 우리가 처음에 작성했던 solidity에 있는 함수이며,

그 문서를 컴파일 한 abi의 내용을 토대로 메서드를 만든다.

 

지금까지 한 배포는 web3 버젼이 1.0의 코드를 이용해서 배포를 했는데

이번에는 이후 버젼(1.2 이후)의 명령어로 다시 작업을 해보자.


굳이 기존의 방식으로 했을때는 contract의 내용을 변경하는 코드가 동작하지 않아 새로운 명령어를 다시 작성해보려한다.

작업순서는

 

  1. solidity 코드 수정
  2. 수정된 코드 컴파일
  3. abi, bytecode 변수 재설정
  4. txObject 변수 재설정
  5. contract, instance 변수 재설정 및 트랜잭션 배포
  6. 마이닝
  7. instance 변수 확인

 

1번 부터해보자

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

contract HelloWorld{
  string text;

  constructor(){
    text = "Hello World";
  }

  function getText() public view returns(string memory){
    return text;
  }

  function setText(string memory value) public{
    text = value;
  }
}

 

setText 라는 함수를 추가했다. 기존에 있는 text라는 변수에 담긴 값을 parameter의 값으로 변경하는 역할을 한다.

기존에 있던 .bin 파일과, .abi 파일을 지운뒤에

 

npx solc --bin --abi contract/helloWorld.sol

 

위의 명령어를 시행해서
컴파일을 다시 해준다.

컴파일된 내용을 가지고 geth console 에서 변수를 재선언 해주자.

 

> bytecode = "0x[.bin 파일 내용]"
> abi = [abi 파일 내용]

 

txObject 도 재선언

 

> txObject = {from:eth.coinbase, data:bytecode}

 

contract와 instance 도 재선언

 

> contract = eth.contract(abi)
> instance = contract.new(txObject)

기존의 명령어를 사용하는 방식은

 

  1. 트랜잭션 발생
  2. 트랜잭션 해시를 통해 트랜잭션 receipt를 출력해서 contractAddress(CA) 확인
  3. instance = contract.at('[ca]')를 통해 instance 선언
  4.  
  5. 위의 과정을 거쳤지만, contract.new(txObject) 명령어는 위의 과정을 한번에 해결해준다.
    즉 트랜잭션을 발생하고 해당 ca를 instance의 저장해두는 역할까지 한번에 진행된다.

instance를 재선언 하면 객체가 출력되는데 맨 밑에 transactionHash가 있다 잘 갖고 있자.

마이닝을 진행한뒤 인스턴스 변수를 확인해보자

 

> miner.start(4)
> miner.stop()
> instance
# 객체 출력됨

 

instance 변수를 다시 확인해보면

객체가 출력되는데 아까 출력됐던 것과 다른 점이 존재한다

 

address가 채워져있다. CA의 내용이다.

 

> instance.getText.call()
# "Hello World"
> instance.setText('hello Kong', {from:eth.coinbase})

 

getText함수를 실행해보면 solidity 문서에서 작성한 "Hello World"가 출력된다.

setText 메서드를실행 시키는데 첫번째 인자값은 우리가 solidity에서 작성한 parameter이고,

두번째 인자는 transaction을 발생시키는 주체이다.

 

> txpool

 

transaction pool을 확인해보면 setText로 인해 발생한 트랜잭션의 내용이 풀에 담겨있다.

다시 마이닝을 통해 트랜잭션을 블록에 담아보자.

 

> miner.start(4)
> miner.stop()

 

마이닝이 되었다면,

setText가 잘 동작하였는지 확인해보기 위해

getText를 다시 실행해보자.

 

> instance.getText.call()
# "hello Kong"

 

개발 과정에서 이모든 명령어를 실행하면서 확인을 한다는건 매우 귀찮을 거다.

그래서 이걸 편하게 해주는 프레임 워크와 웹사이트가 있는데,

프레임워크로는

hardhat과 truffle 이 있고,

 

웹사이트는

remix가 있다.

위의 프레임워크와 remix는 다음에 알아보자

728x90
728x90

댓글