プライベートネット上でのスマートコントラクトの実装

# プライベートネット上でスマートコントラクト実装

## はじめに
本記事はローカルの環境で実装を行っています。
そのため、環境が整っていない方は、下記記事を参考に環境を整えることで、同様の操作で進めることができると思います。

https://qiita.com/git-Ktu/items/a0f5e85f7a656779150a

### 実行環境
Ubuntu 22.04.2
Solidity 0.8.20
geth 1.12.0

### Solidityコンパイラ（solc）のインストール
```
$ sudo add-apt-repository ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install solc
```

インストールの確認
```
$ solc --help
```

---
### HelloWorld.solファイルの作成

バージョン(0.8.20)を使用している

```
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
    function sayHelloWorld() public pure returns (string memory) {
        return "Hello World";
    }
}
```

### コンパイル
下記コマンドでコンパイルを行い、出力内容を記録しておく(トランザクション送信時に使用)
```
$ solc --abi --evm-version paris --bin HelloWorld.sol
```
出力
```
Binary:
長いので省略
6080604052348015~ 長いので省略 ~0008140033
Contract JSON ABI
[{"inputs":[],"name":"sayHelloWorld","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
```

注意
バージョン0.8.20から「--evm-version」のデフォルト値が「shanghai」になっている。
そのため、ローカルでブロックチェーンを起動させている場合、EVMのバージョンとの差により、トランザクションとして送信するときエラーになる可能性がある。
出力されるエラー：「invalid opcode: PUSH0"」
それを回避するため、上記コマンドでは意図的に「--evm-version paris」としている。

---

### トランザクション送信
consoleを指定しそのまま対話型で進めてもよいがログを確認したいため、今回は指定せずに起動
```
$ geth --datadir data --networkid 12345 --nodiscover --mine --unlock 0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3 --miner.etherbase 0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3
```

別ターミナルで対話型コンソールにアタッチする。
```
$ geth attach data/geth.ipc
```

変数にコンパイル時出力されたbinaryとabiを格納する。
binの頭に「0x」を入れておく。
```
> bin = "0x6080604052348~ 長いので省略 ~430008140033"
> abi = [{"inputs":[],"name":"sayHelloWorld","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
> cnt = eth.contract(abi).new({from: eth.accounts[0], data: bin})
```

出力ログ
```
INFO [07-18|18:14:56.971] Setting new local account                address=0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3
INFO [07-18|18:14:56.973] Submitted contract creation              hash=0x044fdca630b208c6f6551636e616da58ae1587ba1ec003924ff19bba4aa91225 from=0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3 nonce=4 contract=0xC5b437a088B58717CD8ead6B65EDCD687eBF4661 value=0
INFO [07-18|18:14:57.004] Commit new sealing work                  number=561 sealhash=fb6553..6d4a63 uncles=0 txs=1 gas=133,111 fees=0.000133111 elapsed="964.6μs"
INFO [07-18|18:14:58.002] Successfully sealed new block            number=561 sealhash=fb6553..6d4a63 hash=672ecd..538112 elapsed=997.683ms
```

ログを見ると、contractのアドレス「0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3」が割り当たってることが確認できる。

---

### contractへのアクセス

contractへアクセスするオブジェクトを作成する。
```
> contract_helloWorld = eth.contract(abi).at(cnt.address)

#出力
{
  abi: [{
      inputs: [],
      name: "sayHelloWorld",
      outputs: [{...}],
      stateMutability: "pure",
      type: "function"
  }],
  address: "0xc5b437a088b58717cd8ead6b65edcd687ebf4661",
  transactionHash: null,
  allEvents: function bound(),
  sayHelloWorld: function bound()
}
```

sayHelloWorldの呼び出し
```
> contract_helloWorld.sayHelloWorld.call()

#出力
"Hello World"
```

## おわりに
プライベートネット環境でのスマートコントラクト実装という感じで進めてみましたがどうでしたでしょうか。
自分自身、バージョンの問題などでかなり時間がかかってしまったんですが、何とか出来てよかったです・・・
やっと環境を作ることができたので、これからSolidityの勉強も進めていきたいと思います

勉強しながら記事の作成をしているので、内容に間違い等ございましたらご指摘よろしくお願いいたします。
日本語の情報が少なかったため、この記事が誰かの役に立てばすごい嬉しいです。