[블록체인] 이더리움 EVM과 Solidity

dhkim·2022년 7월 21일
0

블록체인 뽀개기

목록 보기
18/22
post-thumbnail

EVM에 대한 이해

  1. 솔리디티 설치

Mac

  1. brew update
  2. brew tap ethereum/ethereum
  3. brew install solidity
  1. 버전 확인: solc --version

컴파일

solc를 사용하여 솔리디티 코드를 Bytecode로 컴파일할 수 있습니다. EVM은 Bytecode를 실행합니다.

ABI는 스마트 컨트랙트 코드에 대한 설명이 담긴 JSON 형식의 인터페이스입니다. 각 노드는 이 ABI를 사용하여 상호작용합니다.

  • Bytecode 생성: solc --optimize --bin {파일명}
  • ABI 생성: solc --abi {파일명}

이더리움 개발 환경 구성 - Remix

Remix는 솔리디티 개발을 위한 웹 기반 IDE입니다. Remix는 솔리디티 개발을 위한 컴파일, 배포, 테스트, 디버깅 기능을 내장하고 있습니다.

Remix: remix.ethereum.org

주요 기능

  • 파일 익스플로러(File Explorers): 새로운 파일, 폴더를 만들거나, 깃허브 연동, 로컬 컴퓨터에서 파일 업로드를 할 수 있습니다.
  • 솔리디티 컴파일러(Solidity Compiler): 작성한 컨트랙트 코드를 컴파일합니다.
    ABI, Bytecode를 비롯한 메타 데이터를 확인할 수 있습니다.
  • 배포 및 트랜잭션 실행(Deploy & Run Transactions): 컴파일한 코드를 배포하고, 배포한 컨트랙트를 실행합니다.
    Remix에서 제공하는 가상 환경이나, 실제 이더리움 네트워크에 배포할 수 있습니다.
  • 플러그인 매니저(Plugin Manager): 컨트랙트 개발에 필요한 모듈을 설치 및 관리합니다.

이더리움 테스트넷 환경 - Ropsten 테스트넷 배포 & 이더스캔 검증 및 등록

Ropsten 테스트넷에 컨트랙트 배포

Remix에서 MetaMask 계정을 연결하여 Ropsten 테스트넷와 연결할 수 있습니다. MetaMask 계정을 통해 테스트넷에 작성한 스마트 컨트랙트를 배포할 수 있습니다.

이더스캔에서 컨트랙트 검증 및 등록

사용자가 직접 컨트랙트 코드를 확인하여 어떤 컨트랙트인지 확인하고 컨트랙트를 수행할 수 있게 하기 위해, 이더스캔에서 컨트랙트의 솔리디티 코드를 등록할 수 있습니다.

이더스캔에 특정 컨트랙트에 대한 솔리디티 코드를 제출하면, 이더스캔은 해당 코드가 실제로 등록된 컨트랙트의 바이트코드 및 ABI와 일치하는지 검증합니다. 일치하는 경우, 이더스캔에 솔리디티 코드가 등록됩니다.

Geth와 Web3을 사용해 스마트 컨트랙트 빌드하기

Geth Console에서 이더리움 네트워크에 접속하여, Web3를 사용해 컨트랙트를 배포할 수 있습니다.

  • eth.contract(abi 배열): 컨트랙트 객체를 생성합니다.
  • personal.unlockAccount(eth.accounts[0]): 컨트랙트를 배포할 계정의 락을 풀어줍니다.
  • 컨트랙트객체.net({from, data, gas}): 네트워크로 컨트랙트를 배포합니다. 배포된 컨트랙트 객체가 반환됩니다.

솔리디티 기본 문법 이해

SPDX License Identifier

스마트 컨트랙트 코드에 대한 라이센스를 코드 최상단에 주석 형식으로 표기합니다.

// SPDX-License-Identifier: MIT

Pragma

특정 컴파일러의 버전을 표기합니다.

pragma solidity ^0.8.7; 

상태 변수(State Variables)

상태 변수는 컨트랙트 스토리지에 영구적으로 저장되는 변수입니다.

{데이터 타입} {변수명} = {초기화할 값};  // 선언 및 초기화
  • 값형 데이터타입
      불(bool)
      정수(int, uint)
      고정 바이트 배열 (ex. bytes8)
      주소 (address)
  • 참조형 데이터타입
      배열(ex. uint[])
      문자열(bytes)
      구조체(struct)
      매핑(mapping)
  • 글로벌 변수
      block: 블록에 대한 정보
      msg: 컨트랙트를 시작한 트랜잭션이나 메시지 콜에 대한 정보
      tx: 트랜잭션 데이터
      this: 현재 컨트랙트
  • 상태 변수 접근 수준
      public: 컨트랙트 내에서 직접 접근 가능하다. 컴파일러가 퍼블릭 상태변수에 getter 함수를 생성하고, 외부 컨트랙트나 클라이언트 코드에서 getter 함수를 통해 접근할 수 있다.
      internal: 변수 선언시 디폴트 값. 컨트랙트 및 상속 컨트랙트에서만 접근 가능하다.
      private: 동일한 컨트랙트 멤버만 프라이빗 상태 변수에 접근 가능
  • constant
      상태 변수를 상수로 선언

함수

function 함수이름(파라미터형식1 파라미터1, 파라미터형식2 파라미터2, ...) { ... }
  • 함수 접근 수준
    external: 외부 컨트랙트나 클라이언트 코드에서 호출할 수는 있으나, 컨트랙트 내부에서는 호출 불가능.
    public: 디폴트 값. 컨트랙트 내부, 외부 컨트랙트, 클라이언트 코드에서 사용할 수 있다.
    internal: 컨트랙트 멤버와 상속 컨트랙트에서만 사용할 수 있다.
    private: 컨트랙트 멤버만 사용할 수 있다.
  • view, pure
    상태를 변경하지 않는 읽기 전용 함수에는 view 키워드를 사용한다.
    스토리지에서 변수를 읽거나 쓰지 않는 함수는 pure 키워드를 사용한다.
  • payable
    함수에서 이더를 받는 경우 payable 키워드를 사용한다.
  • constructor, selfdestructor
    constructor는 생성자 함수로, 컨트랙트의 상태를 초기화한다.
    selfdestructor(컨트랙트 생성자의 주소) 함수를 실행하면 컨트랙트를 소멸할 수 있다.

함수 변경자(modifier)

특정 함수를 실행하기 전, 요구 조건을 만족하는 지 확인하는 유사 함수이다.

modifier onlyOwner {
	require(msg.sender == owner);
	_;
}

function destroy() public onlyOwner {
	selfdestruct(owner);
}

상속

contract 객체를 상속할 수 있다. 상속을 통해 컨트랙트에 기능을 추가하거나 확장할 수 있다.

contract ChildContract is ParentContract {
  // ...
}

에러 핸들링

  • revert: 해당 함수를 종료하고 에러를 리턴한다.
  • require, assert: 설정한 조건이 참인지 확인하고, 조건이 거짓이면 에러를 리턴한다.
function buy(uint amount) public payable {
        require(
            amount <= msg.value / 2 ether,  // 주어진 조건이 참이면 넘어가고, 거짓이면 에러 리턴
            "Not enough Ether provided."  // 에러 메시지를 지정할 수 있습니다
        );

        // 송금 진행
    }

열거형(enum)

열거(enum)은 특정 값들로 집합을 지정하고, 집합에 있는 데이터만을 값으로 가집니다.

enum EvalLevel { Bad, Soso, Great }

EvalLevel kimcoding = EvalLevel.Bad // enum형 변수 선언 및 초기화

int16 kimcodingValue = int16(kimcoding); // kimcoding 열거형 값 0을 정수형으로 변환

이벤트

이벤트는 어떤 결과가 발생했을 때 해당 컨트랙트에서 dApp 클라이언트, 또는 다른 컨트랙트에게 전달합니다.

컨트랙트는 event 키워드를 사용해 이벤트를 설정하고, 경우에 따라 emit 키워드를 사용해 이벤트를 실행합니다. 이벤트가 실행된 경우, 트랜잭션에 기록됩니다.

contract coinTransfer {
	// event 이벤트명(파라미터유형1 파라미터1, 파라미터유형2 파라미터2, ...);
	event Transfer(address from, address to, uint256 value); 

	function transfer(address to, address amount) {
		//...
		
		// emit 이벤트명(인자1, 인자2 ...)
		emit Transfer(msg.sender, to, amount);
	}
}

솔리디티 Hello World

// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

contract helloWorld {
		// 함수가 실행되는 동안 greeting 변수를 사용할 수 있습니다.
		// 함수가 끝까지 실행되면 greeting 변수의 값을 반환합니다.
    function renderHelloWorld () public pure returns (string memory greeting){
			greeting = "Hello World!"; 
		}
}
profile
Blockchain developer

0개의 댓글