티스토리 뷰
1. 로컬 테스트넷 실행
$ anvil
2. 최상위 경로에 .env 파일 생성
PRIVATE_KEY=<anvil 실행 시 제공되는 프라이빗 키 중 하나>
RPC_ENDPOINT=http://localhost:8545
이 때 PRIVATE\_KEY
가 0x
로 시작하면 파싱에서가 발생하므로 0x
를 지워준 16진수값만 넣어줍니다.
3. 배포 코드 작성
cmd/deploy/main.go
package main
import (
"context"
"crypto/ecdsa"
"fmt"
token "go-ethereum-example/gen"
"math/big"
"os"
_ "github.com/joho/godotenv/autoload"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Connect to Ethereum client with RPC endpoint
client, err := ethclient.DialContext(ctx, os.Getenv("RPC_ENDPOINT"))
handleError(err)
defer client.Close()
fmt.Println("Successfully connected to Ethereum client")
// Parse wallet private key
privateKey := mustParsePrivateKey()
address := crypto.PubkeyToAddress(privateKey.PublicKey)
fmt.Printf("Deploying contract from address %s\n", address.Hex())
// Get nonce, gas price and chain ID from the Ethereum client
nonce, err := client.PendingNonceAt(ctx, address)
handleError(err)
gasPrice, err := client.SuggestGasPrice(ctx)
handleError(err)
fmt.Printf("Suggested gas price: %s\n", gasPrice)
chainID, err := client.NetworkID(ctx)
handleError(err)
fmt.Printf("Chain ID: %d\n", chainID)
// Create an signer with the private key, chain ID and nonce
signer, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID)
handleError(err)
signer.GasPrice = gasPrice
signer.GasLimit = 3000000
signer.Nonce = big.NewInt(int64(nonce))
// Deploy the contract with initial supply of 1,000,000 tokens
initialSupply := big.NewInt(0).Mul(big.NewInt(1000000), big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18), nil))
_, tx, _, err := token.DeployToken(signer, client, initialSupply)
handleError(err)
fmt.Printf("Transaction hash: %s\n", tx.Hash().Hex())
// Wait for the deployment to be mined
contractAddress, err := bind.WaitDeployed(ctx, client, tx)
handleError(err)
fmt.Printf("Contract deployed! Contract address: %s\n", contractAddress.Hex())
}
func mustParsePrivateKey() *ecdsa.PrivateKey {
rawPrivateKey := os.Getenv("PRIVATE_KEY")
// Parse the private key
privateKey, err := crypto.HexToECDSA(rawPrivateKey)
handleError(err)
return privateKey
}
func handleError(err error) {
if err != nil {
panic(err)
}
}
.env 파일 자동으로 불러오기
import (
...
_ "github.com/joho/godotenv/autoload"
...
)
테스트넷 RPC 클라이언트 연결
// Connect to Ethereum client with RPC endpoint
client, err := ethclient.DialContext(ctx, os.Getenv("RPC_ENDPOINT"))
handleError(err)
defer client.Close()
fmt.Println("Successfully connected to Ethereum client")
16진수 프라이빗 키를 ECDSA 프라이빗 키로 파싱
// Parse wallet private key
privateKey := mustParsePrivateKey()
func mustParsePrivateKey() *ecdsa.PrivateKey {
rawPrivateKey := os.Getenv("PRIVATE_KEY")
// Parse the private key
privateKey, err := crypto.HexToECDSA(rawPrivateKey)
handleError(err)
return privateKey
}
트랜잭션 서명자 생성
address := crypto.PubkeyToAddress(privateKey.PublicKey)
fmt.Printf("Deploying contract from address %s\n", address.Hex())
// Get nonce, gas price and chain ID from the Ethereum client
nonce, err := client.PendingNonceAt(ctx, address)
handleError(err)
gasPrice, err := client.SuggestGasPrice(ctx)
handleError(err)
fmt.Printf("Suggested gas price: %s\n", gasPrice)
chainID, err := client.NetworkID(ctx)
handleError(err)
fmt.Printf("Chain ID: %d\n", chainID)
// Create an signer with the private key, chain ID and nonce
signer, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID)
handleError(err)
signer.GasPrice = gasPrice
signer.GasLimit = 3000000
signer.Nonce = big.NewInt(int64(nonce))
abigen으로 생성된 코드를 통해 스마트 컨트랙트 배포
// Deploy the contract with initial supply of 1,000,000 tokens
initialSupply := big.NewInt(0).Mul(big.NewInt(1000000), big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18), nil))
_, tx, _, err := token.DeployToken(signer, client, initialSupply)
handleError(err)
fmt.Printf("Transaction hash: %s\n", tx.Hash().Hex())
// Wait for the deployment to be mined
contractAddress, err := bind.WaitDeployed(ctx, client, tx)
handleError(err)
fmt.Printf("Contract deployed! Contract address: %s\n", contractAddress.Hex())
4. 스마트 컨트랙트 배포
$ go run ./cmd/deploy/
Successfully connected to Ethereum client
Deploying contract from address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Suggested gas price: 2000000000
Chain ID: 31337
Transaction hash: 0x9b3b8b92cf9370e0a51c4f1f35726385839ef4aba748c42f22d7327f00cca5ad
Contract deployed! Contract address: 0x5FbDB2315678afecb367f032d93F642f64180aa3
5. 전체 코드
'Solidity' 카테고리의 다른 글
[Solitidy+Go] geth로 스마트 컨트랙트 배포하기 - 5. 이벤트 구독 (0) | 2023.12.14 |
---|---|
[Solitidy+Go] geth로 스마트 컨트랙트 배포하기 - 4. 배포된 스마트 컨트랙트와 상호작용 (0) | 2023.12.14 |
[Solitidy+Go] geth로 스마트 컨트랙트 배포하기 - 2. 스마트 컨트랙트로 Go 코드 생성 (0) | 2023.12.13 |
[Solitidy+Go] geth로 스마트 컨트랙트 배포하기 - 1. 초기 구성 (0) | 2023.12.13 |
[Solidity] 재진입 공격 예방 기법 (0) | 2023.10.04 |