-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
andOneBasketball
committed
Nov 23, 2024
1 parent
726b158
commit 6b4b1a4
Showing
11 changed files
with
635 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
Oops, something went wrong.