准备

  1. 安装 solidity编译器

    https://github.com/ethereum/solidity/releases/tag/
    
  2. 安装abi工具

    get clone https://github.com/ethereum/go-ethereum.git
    make devtools
    

构建本地化开发环境

Ganache(正式名称为testrpc)是一个用Node.js编写的以太坊实现,用于在本地开发去中心化应用程序时进行测试。现在我们将带着您完成安装并连接到它。

首先通过NPM安装ganache。

> npm install -g ganache-cli
> ```
>
> 然后运行ganache cli客户端。
>
> ```
> ganache-cli
> ```
>
> 现在连到`http://localhost:8584`上的ganache RPC主机。
>
> ```
> client, err := ethclient.Dial("http://localhost:8545")if err != nil {  log.Fatal(err)}
> ```
>
> 在启动ganache时,您还可以使用相同的助记词来生成相同序列的公开地址。
>
> ```
> ganache-cli -m "much repair shock carbon improve miss forget sock include bullet interest solution"
> ```

### 生成钱包

钱包三要素
- 私钥

- 公钥

- 地址

  示例代码

package main

import ( "crypto/ecdsa" "fmt" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "golang.org/x/crypto/sha3" "log" )

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

privateKeyBytes := crypto.FromECDSA(privateKey)
fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // 私钥内容
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:]) // 公钥内容
address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address) // 公钥地址(钱包地址)
hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:])
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0x96216849c49358b10257cb55b28ea603c874b05e

}




### 开始

1.创建`simple.sol`文件

// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0;

contract SimpleStorage { uint storedData;

function set(uint x) public {
    storedData = x;
}

function get() public view returns (uint) {
    return storedData;
}

}


2. 生成`abi`文件

solc --abi simple.sol -o ./abi


3. 生成EVM字节码文件

solc --bin .\simple.sol -o bin


4. 生成go的调用文件

--abi=abi/SimpleStorage.abi --pkg=store --out=store.go


5. 部署合约

package main

import ( "context" "crypto/ecdsa" "demo1/store" "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "log" "math/big" )

func main() { client, err := ethclient.Dial("http://127.0.0.1:8545") if err != nil { log.Fatal(err) } privateKey, err := crypto.HexToECDSA("f1b3f8e0d52caec13491368449ab8d90f3d222a3e485aa7f02591bbceb5efba5") if err != nil { log.Fatal(err) } publicKey := privateKey.Public() publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) if !ok { log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey") } fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) nonce, err := client.PendingNonceAt(context.Background(), fromAddress) if err != nil { log.Fatal(err) } gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { log.Fatal(err) } chainID, err := client.ChainID(context.Background()) if err != nil { return } auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) if err != nil { return } auth.Nonce = big.NewInt(int64(nonce)) auth.Value = big.NewInt(0) // in wei auth.GasLimit = uint64(300000) // in units auth.GasPrice = gasPrice

address, tx, instance, err := store.DeployStore(auth, client)
if err != nil {
	log.Fatal(err)
}
fmt.Println(address.Hex())   // 0x147B8eb97fD247D06C4006D269c90C1908Fb5D54
fmt.Println(tx.Hash().Hex()) // 0xdae8ba5444eefdc99f4d45cd0c4f24056cba6a02cefbf78066ef9f4188ff7dc0
_ = instance

} ```

https://learnblockchain.cn/docs/solidity/layout-of-source-files.html

https://www.bookstack.cn/read/ethereum-development-with-go-book-zh/transfer-eth-README.md

https://blog.csdn.net/qq_28505809/article/details/124149120

变量修饰符

  • public > 公共状态变量与内部变量的不同之处仅在于编译器会自动为它们生成 getter 函数,这允许其他合约读取它们的值。当在同一个合约中使用时,外部访问(例如this.x)调用 getter,而内部访问(例如x)直接从存储中获取变量值。不生成设置器函数,因此其他合约无法直接修改它们的值。
  • internal > 内部状态变量只能从它们在衍生合同中定义的合同中访问。它们不能被外部访问。这是状态变量的默认可见性级别。
  • private

函数修饰符

  • external > 外部函数是合约接口的一部分,这意味着它们可以从其他合约和交易中调用。f不能在内部调用外部函数(即f()不工作,但this.f()工作)。
  • public > 公共函数是合约接口的一部分,可以在内部调用,也可以通过消息调用。
  • internal > 内部函数只能从当前合约或从它派生的合约中访问。它们不能被外部访问。由于它们没有通过合约的 ABI 暴露给外部,它们可以采用内部类型的参数,如映射或存储引用。
  • private