스마트 컨트랙트 - 2 (23/05/22)

nazzzo·2023년 5월 22일
0

컨트랙트 배포 & 실행


스마트 컨트랙트의 배포와 실행은 다음과 같은 과정을 따릅니다

  1. 솔리디티 코드 작성
  2. 솔리디티 컴파일
  3. 메세지의 데이터 속성에 컴파일된 내용(바이트 코드)을 보내기
  4. 트랜잭션 발동



1. 솔리디티 코드 작성


우선 일반적인 형태의 자바스크립트의 클래스를 먼저 살펴보겠습니다


[class.js]


class Counter {
  value
  constructor(){}
  
  // 상태변수의 값을 변화시킬 setter 함수. 인자값이 필요합니다
  setValue(_value){
  	this.value = _value
  }
  // 상태변수의 값을 불러올 getter 함수. 리턴이 필요합니다
  getValue(){
  	return this.value
  }
}

const counter = new Counter()


counter.getValue // undefined
counter.setValue(1) // counter: { value: 1 }



아래는 솔리디티 문법으로 만든 스마트 컨트랙트인데요
구조와 형태가 클래스 문법과 아주아주 유사합니다

[class.sol]

// SPDX-License-Identifire: MIT
pragma solidity ^0.8.0; // 버전에 대한 명시 필수, ';'도 꼭 기입해야 합니다

// 멤버변수(상태변수)의 타입 지정과 함수의 접근제한자를 생략할 수 없습니다
contract Counter {
  uint256 value;
  constructor(){}
  
  // setter, send ~ 클라이언트로부터 매개변수를 받아야 합니다
  function setValue(uint256 _value) public {
    value = _value; // 값 설정
  }
  
  // getter, call  view ~ 상태변수의 현재값을 리턴하는 함수
  function getValue() public view returns (uint256) {
    return value;
  }
}

// { value : 0 } ~ uint 타입의 초기값


스마트 컨트랙트는 블록체인 네트워크에서 실행되는 계약이며,
이 계약을 호출하여 함수를 실행하는 주체는 클라이언트입니다
그리고 코드의 실행은 EVM(이더리움 가상머신)이 담당해서 계약의 상태를 변경합니다


싱글톤과 상태공유

어떠한 스마트 컨트랙트가 네트워크 상에 배치되었을 때는 하나의 인스턴스만이 존재하게 되는데,
이를 싱글톤이라고 부릅니다
모든 노드들은 하나의 싱글톤 인스턴스들을 공유하고 같은 메모리 주소를 참조합니다
따라서 어느 노드에서 스마트 컨트랙트의 상태를 변경하면 다른 노드에서도 동일한 상태를 볼 수 있습니다


call 메서드와 send 메서드

위 코드에서 getter 함수인 getValue()call 메서드에 해당하며,
코드를 실행할 때 연산이 필요없기 때문에 메서드 호출시 가스를 소모하지 않습니다
(함수에서 view 포함 여부로 판단 가능)

그리고 매개변수를 받아야 하는 setValue()는 값의 변경을 동반하는 sender 메서드로,
이와 같이 연산식이 포함된 함수를 호출하려면 클라이언트에게는 가스 수수료를 감당할 만큼의 코인이 필요합니다


스마트 컨트랙트 코드를 작성할 때는 가스 관리가 아주아주 중요합니다
고로 같은 기능을 만들더라도 연산량을 줄이는 방향으로 코드를 짜는 것이 관건입니다



2. 솔리디티 컴파일


다음은 컴파일 명령어입니다 (*먼저 VSCode에 솔리디티 익스텐션을 설치해둘 것)

npx solc --bin --abi ./class.sol

컴파일 결과 2개의 파일이 생성됩니다

  • class_sol_Counter.bin : EVM이 읽을 수 있는 형태로 변환된 바이너리 코드입니다
  • class_sol_Counter.abi : 사용자가 읽을 수 있는 코드로 바이너리를 조작하기 위한 파일입니다
    (json 형식)

이제 .bin 파일에 담긴 내용(바이트 코드)을 그대로 복사한 뒤
메세지 데이터에 실어서 트랜잭션을 발동시켜보겠습니다


web3.eth
    .sendTransaction({
        from: "0x2c3338e54FE9B1Eb3e53DEc6837ebB27EC9388D6",
        gas: "500000",
        data: "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b5780635524107714610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea26469706673582212207f190c10bb79b204f212237a84288d17cbe5ab62d93b97a504500b25c5f5a52964736f6c63430008120033"
    })
    .then(console.log);


/**
{
  transactionHash: '0x82b9eaf738a0e049db562f07b5c9fd07b4c43eeb38801b1841b2ba299b0d6bbf',
  transactionIndex: 0,
  blockHash: '0xf9144982523704847c4444373ed26cb65af944eb804c0b6c66a4fab3b15a3836',
  blockNumber: 5,
  from: '0x2c3338e54fe9b1eb3e53dec6837ebb27ec9388d6',
  to: null,
  gasUsed: 125677,
  cumulativeGasUsed: 125677,
  contractAddress: '0x14958d12Ced89f9cfC3f3B48BA12822833631e7f', // <-- CA
  logs: [],
  status: true,
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
}
**/

컨트랙트 주소가 생성되는 것을 확인할 수 있습니다


CA(Contract Address)?

CA는 스마트 컨트랙트가 배포된 블록체인 네트워크에서, 해당 스마트 컨트랙트를 고유하게 식별하는 주소를 의미합니다
블록체인 네트워크 상에 배포된 컨트랙트들은 모두 고유의 컨트랙트 주소값을 가지고 있습니다



ABI(Application Binary Interface)?

ABI는 컨트랙트 함수와 매개변수들을 JSON 형식으로 나타낸 리스트입니다
이름처럼 스마트 컨트랙트에서 사용될 인터페이스 역할을 합니다

이 인터페이스는 컨트랙트 내의 어떤 함수를 호출할지를 지정하고,
예측대로 함수가 데이터를 리턴한다는 것을 보장하기 위해 사용합니다



[.abi]

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},
{"inputs":[],"name":"getValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]

[call.js]

const Web3 = require("web3")
const web3 = new Web3("http://127.0.0.1:8545")




const abi = [{inputs:[],stateMutability:"nonpayable",type:"constructor"},
{inputs:[],name:"getValue",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},
{inputs:[{internalType:"uint256",name:"newValue",type:"uint256"}],name:"setValue",outputs:[],stateMutability:"nonpayable",type:"function"}]


const dataCode = web3.eth.abi.encodeFunctionCall({inputs:[],name:"getValue",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"}, [])
console.log(dataCode)




web3.eth
    // call 메서드는 hex값을 반환받습니다
    .call({
        to: "0xb3c52A71e05cA5A806dA789944a9A462f0eA3D38",
        data: dataCode,
    })
    .then(data => {
        // 0x00000000... > hex값을 10진수로 변환하는 메서드
        const result = web3.utils.toBN(data).toString(10)
        console.log(result)
    })

// node call

정리하자면 다음과 같습니다

deploy - 작성한 스마트 컨트랙트를 이더리움 네트워크에 배포하는 것
send - 네트워크에 존재하는 스마트 컨트랙트의 상태를 변경하는 것 (트랜잭션)
call - 네트워크에 존재하는 스마트 컨트랙트의 상태변수를 가져오는 것 (읽기 전용)

오늘은 여기까지...



번외

  • truffle ~ deploy, send, call을 묶어서 하나로 관리할 수 있는 프레임워크입니다
    중요한 것은 매커니즘의 이해. send와 call을 단순 메서드가 아닌 통신의 관점으로 이해하는 것

0개의 댓글