[Solidity+Go] geth로 스마트 컨트랙트 배포하기 - 6. 메타데이터를 사용한 standard json input 생성

geth로 스마트 컨트랙트 배포하기 · 6/7
  1. 1. 초기 구성
  2. 2. 스마트 컨트랙트로 Go 코드 생성
  3. 3. 생성된 Go 코드로 스마트 컨트랙트 배포
  4. 4. 배포된 스마트 컨트랙트와 상호작용
  5. 5. 이벤트 구독
  6. 6. 메타데이터를 사용한 standard json input 생성
  7. 7. standard json input을 사용해 배포한 컨트랙트 검증

1. 메타데이터 생성

$ solc @openzeppelin/=$(pwd)/node_modules/@openzeppelin/ --optimize --metadata --metadata-literal contracts/MyToken.sol -o build --overwrite

@openzeppelin/=$(pwd)/node\_modules/@openzeppelin/ : 컨트랙트에서 사용한 라이브러리의 리매핑 정보
--optimize : 옵티마이저 활성화 (기본 실행 횟수: 200), 앞서 옵티마이저를 사용했기 때문에 마찬가지로 사용
--metadata : 메타데이터 생성
--metadata-literal : 소스 코드를 메타데이터에 포함
contracts/MyToken.sol : 컴파일할 solidity 파일
-o build : 컴파일 결과가 저장될 디렉토리 지정
--overwrite : 이미 컴파일 결과가 존재할 경우, 덮어쓰기


2. 코드 작성

cmd/input/main.go

package main

import (
	"encoding/json"
	"os"
	"path/filepath"
)

type StandardJsonInput struct {
	Language interface{} `json:"language"`
	Sources  Sources     `json:"sources"`
	Settings interface{} `json:"settings"`
}

type Sources map[string]Source

type Source struct {
	Keccak256 string `json:"keccak256"`
	Content   string `json:"content"`
}

func main() {
	f, err := os.Open("build/MyToken_meta.json")
	handleErr(err)

	defer f.Close()

	var metadata map[string]interface{}

	err = json.NewDecoder(f).Decode(&metadata)
	handleErr(err)

	sources := make(Sources)

	metaSources := metadata["sources"].(map[string]interface{})

	for k, v := range metaSources {
		sources[k] = Source{
			Keccak256: v.(map[string]interface{})["keccak256"].(string),
			Content:   v.(map[string]interface{})["content"].(string),
		}
	}

	settings := metadata["settings"].(map[string]interface{})

	delete(settings, "compilationTarget")

	standardJsonInput := StandardJsonInput{
		Language: metadata["language"],
		Sources:  sources,
		Settings: settings,
	}

	standardJsonInputBytes, err := json.MarshalIndent(standardJsonInput, "", "  ")
	handleErr(err)

	// generate directory to current working directory if it doesn't exist
	path := filepath.Join(".", "verify")

	err = os.MkdirAll(path, os.ModePerm)
	handleErr(err)

	// create file in directory
	output, err := os.Create(filepath.Join(path, "MyToken_input.json"))
	handleErr(err)

	defer output.Close()

	// write to file
	_, err = output.Write(standardJsonInputBytes)
	handleErr(err)
}

func handleErr(err error) {
	if err != nil {
		panic(err)
	}
}

메타데이터 파일 불러오기

f, err := os.Open("build/MyToken_meta.json")
handleErr(err)

defer f.Close()

var metadata map[string]interface{}

err = json.NewDecoder(f).Decode(&metadata)
handleErr(err)

메타데이터에서 standard json input을 생성하기 위한 데이터 추출

type StandardJsonInput struct {
	Language interface{} `json:"language"`
	Sources  Sources     `json:"sources"`
	Settings interface{} `json:"settings"`
}

type Sources map[string]Source

type Source struct {
	Keccak256 string `json:"keccak256"`
	Content   string `json:"content"`
}
sources := make(Sources)

metaSources := metadata["sources"].(map[string]interface{})

for k, v := range metaSources {
	sources[k] = Source{
		Keccak256: v.(map[string]interface{})["keccak256"].(string),
		Content:   v.(map[string]interface{})["content"].(string),
	}
}

settings := metadata["settings"].(map[string]interface{})

delete(settings, "compilationTarget")

standardJsonInput := StandardJsonInput{
	Language: metadata["language"],
	Sources:  sources,
	Settings: settings,
}

standard json input 생성

standardJsonInputBytes, err := json.MarshalIndent(standardJsonInput, "", "  ")
handleErr(err)

// generate directory to current working directory if it doesn't exist
path := filepath.Join(".", "verify")

err = os.MkdirAll(path, os.ModePerm)
handleErr(err)

// create file in directory
output, err := os.Create(filepath.Join(path, "MyToken_input.json"))
handleErr(err)

defer output.Close()

// write to file
_, err = output.Write(standardJsonInputBytes)
handleErr(err)

3. 코드 실행

$ go run ./cmd/input

verify/MyToken_input.json 파일이 생성됨


4. 생성된 standard json input 테스트

$ solc --standard-json ./verify/MyToken_input.json

5. 전체 코드