[Ethereum] Goerli 테스트넷에 스마트 컨트랙트 배포

Hardhat을 이용해 Goerli 테스트넷에 스마트 컨트랙트 배포 실습한 내용을 정리하여 올립니다.

메타마스크

저는 주로 크롬을 사용하는데 크롬의 확장 프로그램으로 메타마스크를 설치합니다.

메타마스크는 크립토 월렛을 간편하게 생성할 수 있습니다.

실제 지갑을 가지고 테스트넷에서도 이용할 수 있으니 참고하면 좋을 것 같습니다.

설치 후 뜨는 팝업 페이지에서 [시작하기] 또는 크롬 우측 상단의 [퍼즐 아이콘 > 메타마스크]를 선택해 지갑을 생성합니다.

생성 완료 후 비밀 복구 구문은 꼭 안전한 곳에 보관하세요.

현재 이더리움 메인넷의 이더 보유량이 나옵니다.

우리는 테스트넷을 이용할 것이니 상단에 [이더리움 메인넷]을 눌러 [보기/숨기기 네트워크 해지] 버튼을 눌러 테스트넷이 목록에 나오도록 합니다.

그리고 [Goerli 테스트 네트워크]를 선택합니다.

Goerli

Goerli는 proof-of-authority 방식을 사용하는 이더리움 테스트 네트워크입니다.

우리는 Goerli에서 스마트 컨트랙트를 배포하고 테스트 할겁니다.

Goerli faucet

https://goerlifaucet.com

메타마스크에서 [Goerli 테스트 네트워크]를 선택했을때 새 지갑이니 당연히 보유중인 GoerliETH가 0일겁니다.

Goerli 테스트넷에 스마트 컨트랙트를 배포하고 테스트하기 위해서는 일정량의 GoerliETH가 필요합니다.

파우셋 사이트에서 테스트를 위한 일정량의 GoerliETH를 얻어옵니다.

메타마스크의 상단 중앙에 있는 0x로 시작하는 지갑 주소를 클릭하면 클립보드로 복사됩니다.

복사된 지갑 주소를 파우셋 사이트에서 붙여넣기 하여 0.2 GoerliETH를 받습니다.

사이트의 설명에 따르면 하루에 0.2 GoerliETH를 얻을 수 있다고 합니다.

Alchemy

https://dashboard.alchemy.com/

스마트 컨트랙트의 트랜잭션을 모니터링 하거나 관리하기 위해 Alchemy의 서비스를 이용합니다.

회원 가입 후 [메뉴 Apps > Create App]을 눌러 앱을 생성합니다.

특히 NETWORK는 메인넷이 아닌 Goerli를 선택해주세요.

생성된 App의 우측 상단 VIEW KEY를 눌러 API KEY를 확인하세요.

프로젝트 폴더 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
% mkdir test_smart_contract
% cd test_smart_contract
test_smart_contract % npm init -y
Wrote to /test_smart_contract/package.json:

{
"name": "test_smart_contract",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

Hardhat

https://hardhat.org

Hardhat은 이더리움 소프트웨어 개발 환경을 제공합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
% npm install hardhat
% npm install @nomiclabs/hardhat-ethers ethers
% npx hardhat compile
888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888

👷 Welcome to Hardhat v2.12.5 👷‍

✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /test_smart_contract
✔ Do you want to add a .gitignore? (Y/n) · n
✔ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox)? (Y/n) · y

✨ Project created ✨

See the README.md file for some example tasks you can run

Give Hardhat a star on Github if you're enjoying it! 💞✨

https://github.com/NomicFoundation/hardhat

Please take a moment to complete the 2022 Solidity Survey: https://hardhat.org/solidity-survey-2022

컴파일 실행시 여러 옵션이 뜨는데 자바스크립트 프로젝트를 선택합니다.

위치는 우리가 설정한 현재 위치(디폴트) 값을 선택합니다.

gitIgnore는 현재 실습에서는 아무 옵션이나 상관없습니다.

hardhat-toolbox를 설치하는 옵션을 선택합니다.

test_smart_contract/contracts/Sample.sol 작성

1
2
3
4
5
% cd contracts
// 기존의 예제 파일 Lock.sol 삭제
% rm Lock.sol
remove Lock.sol? y
% touch Sample.sol
Sample.sol
1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Sample{
uint public recvEther;

function send() payable public{
recvEther += msg.value;
}
}

스마트 컨트랙트에 이더를 보내는 간단한 로직입니다.

test_smart_contract/hardhat.config.js 수정

기존의 내용을 삭제하고 아래의 내용으로 대체합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
require('dotenv').config();
require("@nomicfoundation/hardhat-toolbox");

const { API_KEY, PRIVATE_KEY } = process.env;
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url: `https://eth-goerli.alchemyapi.io/v2/${API_KEY}`,
accounts: [PRIVATE_KEY]
}
}
};

dotenv

dotenv는 .env 파일 안에 정보를 작성하고 그 정보를 불러올 수 있습니다.

1
npm install dotenv

.env 파일에는 중요한 API KEY나 URL을 정의하는 경우가 많습니다.

만약 github과 같은 오픈소스로 관리하는 경우 ignore 지정이 필수입니다.

test_smart_contract/.env 파일 생성

1
2
API_KEY="3aXDkjuGnK7FT3qYgy9naFW4la08G3a1"
PRIVATE_KEY={YOUR_PRIVATE_KEY}

위의 내용은 예제입니다.

우측의 값은 실제 여러분의 alchemy API_KEY, 지갑의 PRIVATE_KEY 값을 넣으세요

지갑의 PRIVATE_KEY 값은 메타마스크의 계정 오른 쪽의 ...를 눌러 계정 세부 정보 > 비공개 키 보내기를 누른 후 메타마스크 비밀번호를 입력하여 얻을 수 있습니다.

test_smart_contract/scripts/deploy.js 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const hre = require("hardhat");

async function main() {
const [deployer] = await ethers.getSigners()
console.log(
`Deploying contracts with the account: `, deployer.address
);
const Sample = await hre.ethers.getContractFactory("Sample");
const sample = await Sample.deploy();
console.log(
`Deployed to ${sample.address}`
);
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

스마트 컨트랙트를 배포할 때 사용할 스크립트고 배포에 완료되면 스마트 컨트랙트의 주소를 얻을 수 있습니다.

스마트 컨트랙트 배포

1
2
3
4
5
% npx hardhat --network goerli run scripts/deploy.js
Downloading compiler 0.8.9
Compiled 3 Solidity files successfully
Deploying contracts with the account: 0x92bdf2d42659cDD40d6610B49Fc357A46c0b6aDb
Deployed to 0x1405b7559c745b074b919b92d4ccc0585908b5c7

위의 Deployed to 0x...의 주소를 복사합니다.

이 주소가 배포된 스마트 컨트랙트의 주소입니다.

test_smart_contract/.env에 컨트랙트 주소 추가

1
2
3
API_KEY="3aXDkjuGnK7FT3qYgy9naFW4la08G3a1"
PRIVATE_KEY={YOUR_PRIVATE_KEY}
CONTRACT_ADDRESS="0x1405b7559c745b074b919b92d4ccc0585908b5c7"

test_smart_contract/scripts/interact.js 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const API_KEY = "3aXDkjuGnK7FT3qYgy9naFW4la08G3a1";
const PRIVATE_KEY = {YOUR_PRIVATE_KEY};
const CONTRACT_ADDRESS = "0x1405b7559c745b074b919b92d4ccc0585908b5c7";

const { ethers } = require("ethers");
const contract = require("../artifacts/contracts/Sample.sol/Sample.json");

// provider - Alchemy
const alchemyProvider = new ethers.providers.AlchemyProvider(network="goerli", API_KEY);

// signer - you
const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider);

// contract instance
const sampleContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);

async function main() {
const tx = await sampleContract.send({
value: ethers.utils.parseEther("0.04")
});
await tx.wait();
}

main();

스마트 컨트랙트의 send 함수를 호출하는 스크립트입니다.

현재 코드상에서는 0.04의 이더를 스마트 컨트랙트로 전송합니다.

interact.js 실행

1
% node interact.js

따로 로그 처리를 하지 않았으니 에러가 나지 않았다면 정상적으로 실행됩니다.

전송된 GoerliETH 확인

메타마스크에서 생성한 지갑의 주소와 스마트 컨트랙트 주소를 조회할 수 있는 사이트입니다.

Balance에서 현재 보유중인 이더(실제로는 GoerliETH)와 Transactions에서 Send메소드를 이용해 0.04 이더를 받은것을 확인할 수 있습니다.