본 시리즈에서는, 블록체인과 스마트 컨트랙트가 어떤 건지도 전혀 모르던 어느 주니어가..
약 1년간 스마트 컨트랙트를 호출하는 서버 작업을 접하며 우당탕탕 습득한,
ethers js
라이브러리 활용에 관한 이야기를 담을 예정입니다.
어디까지나 라이브러리 사용에 중점을 둘 예정이기에,
블록체인, 스마트 컨트랙트, EVM 등에 대한 기술적인 깊이를 얻고자 하는 분들을 위한 글은 아닐 것임을 밝힙니다.. 🙇
🙇 잘못된 내용에 대한 지적은 항상 감사드립니다!!
💡 본 시리즈의 모든 내용은
ethers js
v5를 기준으로 작성되었습니다.
❗ 작성일(2023.10.22) 기준 6.8.0버전까지 공개된
ethers js
v6와 상이한 내용이 있을 수 있습니다!
💡 본 포스팅에서는
ethers js
로 블록체인과 상호작용하기 위해 일반적으로 사용되는Provider
,Signer
,Interface
와Contract
클래스에 대한 기본적인 개념을 담으려 합니다.
ethers js 공식 문서
Ethereum Docs
Solidity By Examples
솔리디티 기본 문법
[ 공식 문서 설명 ]
The ethers.js library aims to be a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem.
→ 이더리움 블록체인과 상호작용하기 위한 라이브러리!
| 이더리움뿐만 아니라, EVM(Ethereum Virtual Machine, 이더리움 가상 머신) 기반으로 만들어진 대부분의 체인에 사용이 가능합니다!
[ 공식 문서 설명 ]
A Provider (in ethers) is a class which provides an abstraction for a connection to the Ethereum Network. It provides read-only access to the Blockchain and its status.
Provider
란 네트워크(체인)과의 연결을 추상화한 Class입니다.Provider
클래스로 블록체인에 대한 read-only
함수를 호출할 수 있습니다. 스마트 컨트랙트 개발에 많이 사용되는 Solidity
프로그래밍 언어에서 함수를 작성할 때에는, 함수의 가시성(Visibility)
과 함수의 상태 변경성(State Mutability)
를 선언합니다.
이 중, read-only
접근과 관련되는 함수의 상태 변경성(State Mutability)
에는 크게 아래 3가지 유형이 있습니다.
view
→ read-onlypure
→ read-onlypayable
→ state-mutableProvider
가 read-only라는 것은, Provider
객체만으로는 Solidity
함수의 3가지 상태 변경 유형 중 view
및 pure
함수만을 호출할 수 있다는 의미입니다.
함수의 가시성(Visibility) 에 관하여서는, 추후 실제 스마트 컨트랙트 호출에 관한 내용을 다룰 때 함께 언급하려 합니다. 🙇
[ 예시 (from. SolidityByExample) ]
contract ViewAndPure {
uint public x = 1;
// Promise not to modify the state.
function addToX(uint y) public view returns (uint) {
return x + y;
}
...
}
→ 함수 밖에서 선언한 변수를 뜻하는 상태 변수(State variable)
(여기서는 x
)를 실행 과정에서 변경하지 않는 함수,
즉, 체인의 상태를 변경하지 않는 함수에 view
유형을 사용할 수 있습니다.
[ 예시 (from. SolidityByExample) ]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract ViewAndPure {
uint public x = 1;
...
// Promise not to modify or read from the state.
function add(uint i, uint j) public pure returns (uint) {
return i + j;
}
}
→ 상태 변수의 변경(즉, 체인의 상태 변경)도, 체인의 상태를 읽어오지도 않는 함수에 pure
유형을 사용할 수 있습니다.
→ 실행 과정에서 토큰을 송/수신할 수 있는 함수에 payable
유형을 사용합니다.
ethers js
공식 문서는 DefaultProvider를 사용하여 Provider에 여러 service를 연결하는 것을 권장하고 있지만, 본 포스팅 및 시리즈에서는 역시ethers js
문서에서 많이 사용되는 방법으로 언급된 JsonRpcProvider를 사용할 예정입니다!
→ URL 등으로 JSON-RPC HTTP API에 연결하는 Provider
→ 클라이언트와 블록체인 노드가 통신하기 위한 규약으로, JSON 데이터 형식을 사용!
[ JsonRpcProvider 클래스 초기화 ]
const provider = new ethers.providers.JsonRpcProvider(`${API_URL}`);
[ 공식 문서 설명 ]
A Signer is a class which (usually) in some way directly or indirectly has access to a private key, which can sign messages and transactions to authorize the network to charge your account ether to perform operations.
Signer
자체는 추상 클래스이므로, Wallet
, VoidSigner
, JsonRpcSigner
등의 구현체 sub-class를 이용해야 합니다.Wallet
클래스를 사용하는 것 같습니다 )→ 초기화 과정에서 사용자의 지갑 개인 키를 주입받아,
트랜잭션 실행 과정에서 사용자가 가진 자산을 사용할 수 있도록 트랜잭션에 서명을 진행합니다.
→ 이를 통해, Provider
와 달리 블록체인의 상태를 변경하는 함수 역시 호출이 가능합니다.
(혹시 개념이 낯서신 분들을 위해,
사용자는 블록체인의 상태를 변경하는 트랜잭션을 전송할 때, 일정한 양의 토큰을 지불하며 이를 가스비(gas
)라 합니다)
→ EOA(External Owned Account, 사용자의 지갑)의 개인 키로 트랜잭션 및 메시지에 서명하는 클래스
[ Wallet 클래스의 초기화 ]
// RPC_URL을 주입받은 provider 클래스를 생성합니다.
const provider = new ethers.providers.JsonRpcProvider(`${API_URL}`);
// 지갑의 개인 키와, provider 클래스를 주입하여 Signer 클래스를 생성합니다.
const wallet = new ethers.Wallet(`${EOA_PRIVATE_KEY}`, provider);
The Interface Class abstracts the encoding and decoding required to interact with contracts on the Ethereum network.
→ 스마트 컨트랙트를 네트워크에 배포하면, 배포된 컨트랙트 주소와 함께, 스마트 컨트랙트에 작성된 함수 등을 정의한 인터페이스 정보가 담긴 파일이 반환되는데, 이를 ABI(Application Binary Interface)라 합니다.
[ ABI 예시 (from. Ethers js Docs) ]
[
{
"type":"function",
"name":"transferFrom",
"constant":false,
"payable":false,
"inputs":[
{
"type":"address",
"name":"from"
},
{
"type":"address",
"name":"to"
},
{
"type":"uint256",
"name":"amount"
}
],
"outputs":[]
}
]
Interface
클래스는 ABI를 통해, 실행하고자 하는 함수를 EVM이 이해할 수 있는 형태로 인코딩하여 전송하고, 반환된 결과를 개발자가 이해할 수 있는 형태로 디코딩하는 역할을 담당합니다.
const ABI = abi; //abi는 위의 예시와 같이 배열 형태를 가집니다.
const iface = new ethers.utils.Interface(ABI);
[ 공식 문서 설명 ]
A Contract is an abstraction which represents a connection to a specific contract on the Ethereum Network, so that applications can use it like a normal JavaScript object.
→ 특정한 컨트랙트와의 연결을 추상화한 클래스로, 이를 통해 스마트 컨트랙트와의 상호작용을 일반적인 Javascript 객체를 사용하듯이 진행할 수 있습니다.
// Provider 클래스를 생성
const provider = new ethers.providers.JsonRpcProvider(`${API_URL}`);
// Signer 클래스를 생성
const wallet = new ethers.Wallet(`${PRIVATE_KEY}`, provider);
const contract = new Contract(`${CONTRACT_ADDRESS}`, ABI, signer) // signer 또는 provider