[Ethereum] - ch2. 이더리움 기초

‍허진·2023년 3월 13일
0

Blockchain

목록 보기
15/19
post-thumbnail

본 글은 'Mastering Ethereum(Andreas M.Antonopoulos, Gavin Wood 저)'을 바탕으로 작성되었습니다.

이번에는 이더리움에 대해 알아보고, 지갑 사용 방법과 트랜잭션 생성 방법, 기본 스마트 컨트랙트 수행 방법에 대해 알아보자.

> 이더 화폐 단위

이더리움의 화폐 단위는 이더(ether)라고 불리며, 'ETH'를 사용한다.

사람들이 '이더리움' 화폐라고 언급하는 경우도 있는데, 이것은 초보자의 흔한 실수다. 이더리움은 시스템이고, 이더가 화폐다.

이더는 더 작은 단위로 세분화되어 웨이(wei)라는 가능한 가장 작은 단위까지 내려간다. 또한 이더는 다양한 단위를 가지는데, SI(International System of Units)를 이용한 학명을 사용한다.

값(웨이)멱지수일반 이름SI 이름
11웨이(wei)웨이
1,00010^3배비지(babbage)킬로웨이(kilowei) 또는 펨토이더(femtoether)
1,000,00010^6러브레이스(lovelace)메가웨이(megawei) 또는 피코이더(picoether)
1,000,000,00010^9샤넌(shannon)기가웨이(gigawei) 또는 나노이더(nanoether)
1,000,000,000,00010^12사보(szabo)마이크로이더(microether) 또는 마이크로(micro)
1,000,000,000,000,00010^15피니(finney)밀리이더(miliether) 또는 밀리(milli)
1,000,000,000,000,000,00010^18이더(ether)이더
1,000,000,000,000,000,000,00010^21그랜드(grand)킬로이더(kiloether)
1,000,000,000,000,000,000,000,00010^24메가이더(megaether)

[표 - 이더 명칭과 단위 명칭]

> 테스트 이더

지갑을 설치해서 테스트 이더를 받아보자. 구체적인 실행 과정은 다음을 참고하도록 하자.

이더리움 테스트넷 사용법 기초

위의 설명을 따라하면 자신의 지갑으로 테스트 이더를 받을 수 있고, 트랜잭션 내역을 블록 탐색기에서 확인할 수 있다.

> 월드 컴퓨터 소개

지갑을 만들고 이더를 보내고 받는 과정에서 우리는 이더리움을 암호화폐로 취급했다. 그러나 이더리움은 이보다 훨씬 더 많은 기능을 갖고 있다. 사실, 암호화폐 기능은 탈중앙화된 월드 컴퓨터로서 이더리움의 기능에 부차적인 것이다. 이더는 이더리움 가상 머신(Ethereum Virtual Machine, EVM)이라고 하는 에뮬레이트된 컴퓨터에서 실행되는 컴퓨터 프로그램인 스마트 컨트랙트(smart contract)를 실행하는 데 사용되기 위한 것이다.

EVM은 글로벌 싱글톤으로, 마치 전 세계에 걸친 단일 인스턴스 컴퓨터인 것처럼 작동하며 세상 어디에서든 실행된다. 이더리움 네트워크의 각 노드는 컨트랙트 실행을 확인하기 위해 EVM의 로컬 사본을 실행하고, 이더리움 블록체인은 트랜잭션과 스마트 컨트랙트를 처리할 때 월드 컴퓨터의 변화하는 상태(state)를 기록한다.

> 외부 소유 계정(EOA) 및 컨트랙트

이더리움에는 크게 두 가지 유형의 계정이 있다고 할 수 있다. 하나는 외부 소유 계정(Externally Owned Account, EOA) 이고, 하나는 컨트랙트 계정(contract account)이다.

외부 소유 계정은 개인키가 있는 계정이다. 이는 자금 또는 컨트랙트에 대한 접근을 제어한다. 컨트랙트 계정은 외부 소유 계정과 다르게 스마트 컨트랙트 코드가 있다. 또한, 컨트랙트 계정에는 개인키가 없다. 대신, 컨트랙트 계정은 스마트 컨트랙트 코드의 로직으로 제어한다. 여기서 스마트 컨트랙트 코드는 컨트랙트 계정 생성 시 이더리움 블록체인에 기록되고 EVM에 의해 실행되는 소프트웨어 프로그램이다.

컨트랙트는 외부 소유 계정과 마찬가지고 주소가 있으며, 트랜잭션의 목적지가 컨트랙트 주소일 때 트랜잭션과 트랜잭션 데이터를 입력으로 사용하여 컨트랙트가 EVM에서 실행된다(run). 이더 외에도 트랜잭션에는 실행할 컨트랙트의 특정 함수와 해당 함수에 전달할 파라미터를 나타내는 데이터(data)가 포함될 수 있다. 이렇게 해서 트랜잭션은 컨트랙트 내의 함수를 호출(call)할 수 있다.

> 간단한 컨트랙트 : 테스트 이더 Faucet

이더리움의 스마트 컨트랙트 프로그래밍에서 가장 많이 사용되고 있는 언어는 바로 '솔리디티(Solidity)'다. 솔리디티는 '마스터링 이더리움'의 공동 저자인 개빈 우드 박사가 창안하였다.

// SPDX-License-Identifier: CC-BY-SA-4.0

// Version of Solidity compiler this program was written for
pragma solidity 0.6.4;

// Our first contract is a faucet!
contract Faucet {
    // Accept any incoming amount
    receive() external payable {}

    // Give out ether to anyone who asks
    function withdraw(uint withdraw_amount) public {
        // Limit withdrawal amount
        require(withdraw_amount <= 100000000000000000);

        // Send the amount to the address that requested it
        msg.sender.transfer(withdraw_amount);
    }
}

[Faucet.sol : Faucet을 구현하는 솔리디티 컨트랙트]

위의 코드는 간단하게 Faucet을 구현한 코드이다. 물론 간단하게 구현했기에 취약점도 존재하지만, 일단은 그냥 넘어가도록 하자.

이 글에서는 코드 각각이 어떤 걸 의미하는지 굳이 말하지 않겠다. 솔리디티 언어에 대해 공부하고 싶다면, 다음 사이트를 이용하자.
Cryptozombies로 솔리디티 공부하기

> Faucet 컨트랙트 컴파일

위의 코드를 솔리디티 컴파일러를 사용하여 컴파일(바이트코드로 변환)해보자. 우리는 EVM을 이용하여 이 작업을 수행할 수 있다. 여기서는 유명한 IDE(Integrated Development Environment, IDE) 중 하나인 리믹스(Remix)를 사용해보자.

리믹스 바로가기


[그림 - Faucet 예제 코드 복사]

리믹스에서 새로운 파일(Faucet.sol)을 만들고 위의 코드를 복사하여 붙여보았다. 그 다음 Compile 탭에 가서 컴파일 하면 'Faucet'이 표시되고, 이는 컴파일이 성공적으로 완료되었음을 의미한다.


[그림 - 리믹스가 Faucet.sol 컨트랙트를 성공적으로 컴파일한다.]

> 블록체인에 컨트랙트 생성하기

이제는 이더리움 블록체인에 컨트랙트를 '등록'해야 한다. 여기서 이전에 만들었던 지갑을 사용하여 테스트넷 블록체인에 올려볼 것이다.

블록체인에 컨트랙트를 등록하는 것은 목적지 주소가 0x0000000000000000000000000000000000000000(제로 어드레스)인 특수 트랜잭션을 만드는 것이다. 제로 어드레스는 컨트랙트를 등록하고자 하는 이더리움 블록체인에 알리는 특별한 주소다. 다행히도 리믹스 IDE가 이 모든 것을 처리하고 메타마스크에 트랜잭션을 보낸다.

먼저 'DEPLOY & RUN TRANSACTION' 탭에 가서 Environment를 'Injected Provider - Metamask'로 변경한다. 이렇게 하면 리믹스 IDE가 메타마스크 지갑에 연결되고, 메타마스크를 통해 테스트넷 네트워크에 연결된다.


[그림 - DEPLOY & RUN TRANSACTION 탭]

그 후 Contract에 아까 컴파일한 Faucet이 있는 것을 확인한 후, 'Deploy' 버튼을 누르면 리믹스가 '생성' 트랜잭션을 생성할 것이다. 메타마스크는 우리에게 승인을 요청할 것이다. 컨트랙트 생성 트랜잭션에는 이더가 없지만, 258바이트의 데이터가 있으며 가스를 소비한다.


[그림 - 컨트랙트 생성 트랜잭션을 보여주는 메타마스크]

확인을 누르면 약 15~30초 후에 컨트랙트가 생성되고, 하단에 나타나게 된다.

[그림 - 배포된 Faucet 컨트랙트]

Faucet 컨트랙트는 이제 자체 주소를 갖고 있다. 리믹스에서는 'FAUCET AT 0xA2B...CE6F2'로 나타난다.

> 컨트랙트 사용하기

지금까지 배운 내용을 요약해보자. 이더리움 컨트랙트는 EVM이라고 하는 가상 시스템에서 실행되는 돈을 제어하는 프로그램이다. 컨트랙트는 블록체인에 바이트코드를 등록하는 특별한 트랜잭션에 의해 생성된다. 컨트랙트가 블록체인에서 생성되면 지갑과 마찬가지로 이더리움 주소를 갖게 된다. 누군가가 컨트랙트 주소로 트랜잭션을 보낼 때마다 그 트랜잭션을 입력값으로 하여 컨트랙트가 EVM에서 실행된다. 컨트랙트 주소로 보내지는 트랜잭션에는 이더, 데이터 또는 둘 다를 포함할 수 있다. 트랜잭션이 이더를 포함하면, 이는 컨트랙트 잔액에 '예치된다'. 데이터가 포함되어 있으면 데이터에서는 컨트랙트에서 명명된 함수를 지정하고 호출하여 함수에 인수를 전달할 수 있다.

> 블록 탐색기에서 컨트랙트 주소 보기

자신이 사용했던 테스트 네트워크의 etherscan 페이지에서 아까 생성된 컨트랙트의 주소를 검색해보자. 그리하면 컨트랙트 생성 트랜잭션이 생성된 것을 확인할 수 있다.

> 컨트랙트 자금 조달

현재 컨트랙트에는 생성 트랜잭션 하나만 기록되어 있다. 그러나 Faucet에는 자금이 필요하다! 자금을 조달하기 위해 메타마스크에서 컨트랙트 주소로 이더를 보낼 수 있다.

> 컨트랙트에서 출금

이번에는 Faucet에서 일부 자금을 출금해보자. 출금하려면 withdraw 함수를 호출하고 withdraw_amount 인수를 전달하는 트랜잭션을 생성해야 한다. 이 작업은 리믹스에서 간단하게 수행할 수 있다.

아까 보았던 Deployed Contracts에서 withdraw 옆에 출금할 이더를 쓰고 withdraw를 눌러보자. 여기서 주의할 것은, 이더리움의 화폐 가치가 웨이(wei)로 표시되므로, 우리도 웨이 단위로 입력해야 한다.


[그림 - 리믹스에서 Faucet.sol의 출금 함수 withdraw]

이러한 컨트랙트의 리믹스 인터페이스를 통해 컨트랙트에 정의된 함수를 호출하는 트랜잭션을 구성할 수 있다. 메타마스크는 승인을 위한 트랜잭션 창을 팝업으로 연다. 확인을 누르면 컨트랙트에서 출금이 진행된다.


[그림 - 출금 기능을 호출하는 메타마스크 트랜잭션]

성공적으로 출금이 완료되었다. 이는 리믹스 인터페이스에서도 확인할 수 있다.

[그림 - Faucet 컨트랙트에서 출금이 완료된 상황]

잔액(Balance)이 0.009ETH에서 0.00899ETH로 변한 것을 확인할 수 있다.

이러한 0.00001ETH 전송은 컨트랙트 코드에서 시작되었기 때문에 내부 트랜잭션이다. 이 '내부 트랜잭션'은 Faucet.sol의 withdraw 함수를 통해 다음 코드 줄에서 컨트랙트에 의해 전송되었다.

msg.sender.transfer(withdraw_amount);

요약하자면, 우리는 메타마스크 지갑에서 withdraw_amount 인수 0.00001ETH를 사용하여 withdraw 함수를 호출하는 데이터 명령어가 포함된 트랜잭션을 보냈다. 이 트랜잭션으로 컨트랙트가 EVM 내부에서 실행되었다. EVM이 Faucet 컨트랙트의 withdraw 함수를 실행함에 따라 먼저 require 함수를 호출하고 우리의 금액이 0.1이더의 최대 허용출금보다 자거나 같음을 확인한다. 그런 다음 transfer 함수를 호출하여 이더를 보낸다. transfer 함수를 실행하면 내부 트랜잭션이 생성되어 0.00001이더가 컨트랙트 잔액에서 우리의 지갑 잔액으로 들어온다.

profile
매일 공부하기 목표 👨‍💻 

0개의 댓글