Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
andOneBasketball committed Nov 23, 2024
1 parent 726b158 commit 6b4b1a4
Show file tree
Hide file tree
Showing 11 changed files with 635 additions and 3 deletions.
9 changes: 9 additions & 0 deletions accountBalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ func main() {
}
fmt.Println(balance) // 25893180161173005034

// 获取最新区块上的 nonce 值
nonce, err := client.NonceAt(context.Background(), account, nil)
if err != nil {
log.Fatal(err)
}

// 打印 nonce 值
fmt.Printf("Nonce value: %d\n", nonce)

blockNumber := big.NewInt(37)
balanceAt, err := client.BalanceAt(context.Background(), account, blockNumber)
if err != nil {
Expand Down
40 changes: 40 additions & 0 deletions calculateContractAddress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

// 计算合约部署的地址

import (
"fmt"
"log"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)

// Keccak256 is a utility function to perform a Keccak-256 hash
func Keccak256(data []byte) []byte {
hash := crypto.Keccak256Hash(data)
return hash.Bytes()
}

// CreateAddress generates an Ethereum contract address from an account address and nonce
func CreateAddress(b common.Address, nonce uint64) common.Address {
// RLP encode the account address and nonce
data, err := rlp.EncodeToBytes([]interface{}{b, nonce})
if err != nil {
log.Fatalf("Failed to RLP encode: %v", err)
}

// Perform Keccak256 hashing and take the last 20 bytes (160-bit address)
hash := Keccak256(data)
return common.BytesToAddress(hash[12:]) // Take the last 20 bytes
}

func main() {
// Example usage
address := common.HexToAddress("f39fd6e51aad88f6f4ce6ab8827279cfffb92266")
nonce := uint64(29) // Example nonce

contractAddress := CreateAddress(address, nonce)
fmt.Println("Contract Address:", contractAddress.Hex())
}
93 changes: 93 additions & 0 deletions deployContract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"bytes"
"context"
"crypto/ecdsa"
"fmt"
"log"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)

// 合约字节码,假设你有已编译的合约字节码
var contractBytecode = common.FromHex("608060405234801561001057600080fd5b5060405161013838038061013883398181016040528101906100329190610051565b8060009080519060200190610044929190610051565b50610119565b828054610058906100bd565b90600052602060002090601f01602090048101928261007a57600085556100c1565b82601f1061009357805160ff19168380011785556100c1565b828001600101855582156100c1579182015b828111156100c05782518255916020019190600101906100a5565b5b5090506100ce91906100d2565b5090565b5b808211156100eb5760008160009055506001016100d3565b5090565b600080fd5b6100ff61010e565b61010781610109565b50565b5b5600a165627a7a72305820f89cba2e7c907b4b08c263ff6ba7dd0fcf93871db44c930e5be435e8968c27a40029") // 一个简单的合约字节码

// Create2Address 根据创建者地址、盐值和合约字节码计算合约地址
func Create2Address(deployer common.Address, salt [32]byte, bytecode []byte) common.Address {
// 将数据拼接
data := append([]byte{0xff}, deployer.Bytes()...) // 0xff 常量
data = append(data, salt[:]...) // 盐值
data = append(data, crypto.Keccak256(bytecode)...) // 合约字节码的 keccak256 哈希值

// 计算 keccak256 并返回最后 20 字节(地址)
return common.BytesToAddress(crypto.Keccak256(data)[12:])
}

func main() {
// 创建以太坊客户端
client, err := ethclient.Dial("http://localhost:8545")
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}

// 使用私钥生成一个新账户(用来部署合约)
privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
if err != nil {
log.Fatalf("Failed to generate key: %v", err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatalf("Cannot cast public key to ECDSA")
}
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)

// 设置部署合约时的盐值
var salt [32]byte
copy(salt[:], []byte("my_salt_value"))

// 计算合约地址
contractAddress := Create2Address(fromAddress, salt, contractBytecode)
fmt.Println("Expected contract address:", contractAddress.Hex())

// 获取合约 ABI(在这个例子中我们使用一个空的 ABI)
parsedABI, err := abi.JSON(bytes.NewReader([]byte("[]"))) // 空的 ABI
if err != nil {
log.Fatalf("Failed to parse ABI: %v", err)
}

// 获取合约部署者的 nonce
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
log.Fatalf("Failed to get nonce: %v", err)
}

// 设置 gasPrice 和 gasLimit
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
log.Fatalf("Failed to get gas price: %v", err)
}

auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) // 使用 Go-Ethereum 的 bind 包
if err != nil {
log.Fatalf("Failed to create transactor: %v", err)
}
auth.Nonce = big.NewInt(int64(nonce))
auth.Value = big.NewInt(0) // 部署合约无需发送 ETH
auth.GasLimit = uint64(3000000) // Gas limit
auth.GasPrice = gasPrice

// 部署合约(使用 create2 部署)
tx, _, _, err := bind.DeployContract(auth, parsedABI, contractBytecode, client, salt[:])
if err != nil {
log.Fatalf("Failed to deploy contract: %v", err)
}

fmt.Printf("Contract deployed! tx hash: %s\n", tx.Hex())
}
103 changes: 103 additions & 0 deletions deployToken.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package main

import (
"context"
"crypto/ecdsa"
"fmt"
"log"
"math/big"

"github.com/andOneBasketball/Test-Go-ETH/contracts/Token"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)

func main() {
client, err := ethclient.Dial("http://127.0.0.1:8545/")
if err != nil {
log.Fatal(err)
}

// 私钥初始化
privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
if err != nil {
log.Fatal(err)
}

// 公私钥账户地址转换
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("error casting public key to ECDSA")
}
fmt.Printf("publicKey is: %x\n", crypto.CompressPubkey(publicKeyECDSA))
fmt.Printf("privateKey is: %x\n", crypto.FromECDSA(privateKey))

fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
fmt.Printf("address is: %x\n", fromAddress)
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
//nonce, err := client.NonceAt(context.Background(), fromAddress, big.NewInt(25))
if err != nil {
log.Fatal(err)
}
log.Printf("nonce: %d\n", nonce)

gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
log.Fatal(err)
}

auth := bind.NewKeyedTransactor(privateKey)
auth.Nonce = big.NewInt(int64(nonce))
auth.Value = big.NewInt(0) // in wei
// auth.GasLimit = uint64(300000) // in units
auth.GasPrice = gasPrice

//account := common.HexToAddress("0x5639Bc2D96c7bA37EECA625599B183241A2bBE6c")
address, tx, instance, err := Token.DeployToken(auth, client)
if err != nil {
log.Fatal(err)
}
fmt.Println("contract address: ", address.Hex())
log.Printf("tx hash: %s", tx.Hash().Hex())
log.Printf("chainID: %s", tx.ChainId())
log.Printf("type: %d", tx.Type())
log.Printf("gas limit: %d", tx.Gas())
log.Printf("gas price: %d", tx.GasPrice())
log.Printf("gas fee cap: %s", tx.GasFeeCap())
log.Printf("gas tip cap: %s", tx.GasTipCap())

countAddress, err := instance.Counter(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("count address is: %s\n", countAddress.Hex()) // 0x0

// 需要重新获取 nonce 才能发交易
nonce, err = client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
log.Fatal(err)
}
log.Printf("second nonce: %d\n", nonce)
auth.Nonce = big.NewInt(int64(nonce))

accountB := common.HexToAddress("0xde05927035b51C5f6dE27b427e4649123723e141")
tx, err = instance.Transfer(auth, accountB, big.NewInt(100))
if err != nil {
log.Fatal("Transfer failed: ", err)
}

balance, err := instance.BalanceOf(&bind.CallOpts{}, fromAddress)
if err != nil {
log.Fatal(err)
}
fmt.Printf("account %s balance is: %v\n", fromAddress.Hex(), balance) // 25893180161173005034

balance, err = instance.BalanceOf(&bind.CallOpts{}, accountB)
if err != nil {
log.Fatal(err)
}
fmt.Printf("accountB %s balance is: %v\n", accountB.Hex(), balance) // 25893180161173005034
}
37 changes: 37 additions & 0 deletions getWalletAddress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"crypto/ecdsa"
"fmt"
"log"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/sha3"
)

func main() {
privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
if err != nil {
log.Fatal(err)
}

privateKeyBytes := crypto.FromECDSA(privateKey)
fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}

publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5

address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address) // 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266

hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:])
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ require (
github.com/supranational/blst v0.3.13 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/sys v0.27.0 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand All @@ -188,9 +190,12 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
Expand Down
67 changes: 67 additions & 0 deletions monitorBlock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package main

import (
"context"
"fmt"
"log"
"time"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)

const Confirmations = 6 // 等待 6 个确认区块

func main() {
client, err := ethclient.Dial("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID")
if err != nil {
log.Fatal(err)
}

// 创建一个用于监听新区块的通道
headers := make(chan *types.Header)
sub, err := client.SubscribeNewHead(context.Background(), headers)
if err != nil {
log.Fatal(err)
}

// 缓存区块及其确认数
blockCache := make(map[uint64]*types.Block)

fmt.Println("Listening for new blocks...")

for {
select {
case err := <-sub.Err():
log.Fatal(err)
case header := <-headers:
block, err := client.BlockByHash(context.Background(), header.Hash())
if err != nil {
log.Fatal(err)
}

blockNumber := block.Number().Uint64()
fmt.Printf("New block received: %d\n", blockNumber)

// 将新接收到的区块缓存
blockCache[blockNumber] = block

// 检查之前未确认的区块是否已经得到了6个确认
for blockNumber, cachedBlock := range blockCache {
latestBlockNumber, err := client.BlockNumber(context.Background())
if err != nil {
log.Fatal(err)
}

if latestBlockNumber >= blockNumber+Confirmations {
// 该区块已确认6个区块,可以安全处理
fmt.Printf("Block %d has been confirmed after 6 blocks\n", blockNumber)
// 在这里处理业务逻辑
delete(blockCache, blockNumber) // 移除已处理的区块
}
}
}
// 暂停短时间,以防止频繁查询最新区块号
time.Sleep(time.Second * 2)
}
}
Loading

0 comments on commit 6b4b1a4

Please sign in to comment.