[Ethereum] Ganacheにデプロイ

コントラクトをデプロイする3種類の方法
– Ganacheにデプロイ(ローカルブロックチェーン)
– Parityを使ってGoerliテストネットワークにコントラクをデプロイ
– Infuraを使ってRinkebyテストネットワークにデプロイ

デプロイはtruffle migrateを使う

$ truffle compile
build/contractsの下にファイルが作成される
アプリケーションバイナリインターフェイスがABI
bytecodeはコンパイルした結果

$ cp -r hoscdev/chapter-5/greeter/client greeter/client

truffle-config.js

module.exports = {
   contracts_build_directory: "./client/src/contracts",
}

$ truffle compile
$ cd client
$ npm install
$ npm run start
http://192.168.33.10:3000/

### Ganacha-CLI
どうやらローカルからGanachaは使えないみたいなので
$ curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add –
$ echo “deb https://dl.yarnpkg.com/debian/ stable main” | sudo tee /etc/apt/sources.list.d/yarn.list
$ sudo apt update && sudo apt install yarn
$ yarn –version
1.22.15
$ yarn add ganache-cli

error jsdom@19.0.0: The engine “node” is incompatible with this module. Expected version “>=12”. Got “10.24.1”

truffle-config.jsをローカルに落としてもう一度やってみる

ganacheのMNEMONICをコピーする
Metamaskを一旦Chrome extensionから解除、再設定して、mnemonicを入力する

$ truffle migrate –network development

Compiling your contracts…
===========================
> Everything is up to date, there is nothing to compile.

Starting migrations…
======================
> Network name: ‘development’
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)

1_initial_migration.js
======================

Replacing ‘Migrations’
———————-
> transaction hash: 0x569e2101661c8336ea93eabe22e32ce7edd755f2ec231db1df269c699141fa9e
> Blocks: 0 Seconds: 0
> contract address: 0x9d1cB4d7659Ff924A9F929AD0abD072CA0ABC103
> block number: 1
> block timestamp: 1639442039
> account: 0xf6C3c58654B7005C200587f552980CaE09b0B7d1
> balance: 99.99615706
> gas used: 192147 (0x2ee93)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00384294 ETH

> Saving migration to chain.
> Saving artifacts
————————————-
> Total cost: 0.00384294 ETH

2_deploy_greeter.js
===================

Replacing ‘Greeter’
——————-
> transaction hash: 0x7903ecd10332145b40bf013d79b5e00846f4c77a1c5bdf480624e36200c41957
> Blocks: 0 Seconds: 0
> contract address: 0xC9A75Fc25626AB7907783F0440BD4e6fed30A54D
> block number: 3
> block timestamp: 1639442040
> account: 0xf6C3c58654B7005C200587f552980CaE09b0B7d1
> balance: 99.9888452
> gas used: 323255 (0x4eeb7)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0064651 ETH

> Saving migration to chain.
> Saving artifacts
————————————-
> Total cost: 0.0064651 ETH

Summary
=======
> Total deployments: 2
> Final cost: 0.01030804 ETH

うーん、概念がよくわからん
MetaMaskでインポートphraseでログインしても入ってないんだよな..

[Ethereum] Hello World!

Solidityでは、入出力などはアクセスできない 関数のみ

const GreeterContract = artifacts.require("Greeter");

contract("Greeter", () => {
	it("has been deployed successfully", async() => {
		const greeter = await GreeterContract.deployed();
		assert(greeter, "contract was not deployed");
	});

	describe("greet()", () => {
		it("returns 'Hello World!'", async() => {
			const greeter = await GreeterContract.deployed();
			const expected = "Hello World!"
			const actual = await greeter.greet();
			assert.equal(actual, expected, "Greeted with 'Hello World!'")
		})
	})
});

コントラクトに関数を追加

contract Greeter {
	
	function greet() external pure returns(string memory){
		return "Hello World!";
	}
}

$ truffle test
Contract: Greeter
✓ has been deployed successfully
greet()
✓ returns ‘Hello World!’

2 passing (78ms)

状態を変更しない関数は pure または view

### Contractを動的にする
greeter_test.js

contract("Greeter: update greeting", ()=> {
	describe("setGreeting(string)", ()=> {
		it("sets greeting to passed in string", async() => {
			const greeter = await GreeterContract.deployed();
			const expected = "Hi there!";

			await greeter.setGreeting(expected);
			const actual = await greeter.greet();

			assert.equal(actual, expected, "greeting was not updated");
		});
	});
});

Greeter.sol

contract Greeter {
	string private _greeting = "Hello World!";
	
	function greet() external view returns(string memory){
		return _greeting;
	}

	function setGreeting(string calldata greeting) external {
		_greeting = greeting;
	}
}

テストにパスする

### GreeterをOwnableにする
geter関数ownerを呼び出すことで誰が所有者か確認する

contract("Greeter", () => {
	it("has been deployed successfully", async() => {
		const greeter = await GreeterContract.deployed();
		assert(greeter, "contract was not deployed");
	});

	describe("greet()", () => {
		it("returns 'Hello World!'", async() => {
			const greeter = await GreeterContract.deployed();
			const expected = "Hello World!"
			const actual = await greeter.greet();
			assert.equal(actual, expected, "Greeted with 'Hello World!'")
		})
	})

	describe("owner()", () => {
		it("returns the address of the owner", async()=> {
			const greeter = await GreeterContract.deployed();
			const owner = await greeter.owner();
			assert(owner, "the current owner");
		})
	})
});
contract Greeter {
	string private _greeting = "Hello World!";
	address private _owner;

	function greet() external view returns(string memory){
		return _greeting;
	}

	function setGreeting(string calldata greeting) external {
		_greeting = greeting;
	}

	function owner() public view returns(address){
		return _owner;
	}
}

所有者のアドレスがデプロイ元のアドレスと同じであることをテストしたい
truffleではaccounts変数を使ってアカウントにアクセスできる

contract("Greeter", (accounts) => {
	it("has been deployed successfully", async() => {
		const greeter = await GreeterContract.deployed();
		assert(greeter, "contract was not deployed");
	});

	describe("greet()", () => {
		it("returns 'Hello World!'", async() => {
			const greeter = await GreeterContract.deployed();
			const expected = "Hello World!"
			const actual = await greeter.greet();
			assert.equal(actual, expected, "Greeted with 'Hello World!'")
		})
	})

	describe("owner()", () => {
		it("returns the address of the owner", async()=> {
			const greeter = await GreeterContract.deployed();
			const owner = await greeter.owner();
			assert(owner, "the current owner");
		});

		it("matches the address that originally deployed the contract", async() => {
			const greeter = await GreeterContract.deployed();
			const owner = await greeter.owner();
			const expected = accounts[0];
			assert.equal(owner, expected, "matches address used to deploy contract");
		})
	})
});
contract Greeter {
	string private _greeting = "Hello World!";
	address private _owner;

	constructor() public {
		_owner = msg.sender;
	}

	function greet() external view returns(string memory){
		return _greeting;
	}

	function setGreeting(string calldata greeting) external {
		_greeting = greeting;
	}

	function owner() public view returns(address){
		return _owner;
	}
}

$ npm install openzeppelin-solidity

変更前

pragma solidity >= 0.4.0 < 0.7.0;

contract Greeter {
	string private _greeting = "Hello World!";
	address private _owner;

	constructor() public {
		_owner = msg.sender;
	}

	modifier onlyOwner(){
		require(
			msg.sender == _owner,
			"Ownable: caller is not the owner"
		);
		_;
	}

	function greet() external view returns(string memory){
		return _greeting;
	}

	function setGreeting(string calldata greeting) external onlyOwner{
		_greeting = greeting;
	}

	function owner() public view returns(address){
		return _owner;
	}


}

import "openzeppelin-solidity/contracts/access/Ownable.sol";

contract Greeter is Ownable {
	string private _greeting = "Hello World!";



	function greet() external view returns(string memory){
		return _greeting;
	}

	function setGreeting(string calldata greeting) external onlyOwner{
		_greeting = greeting;
	}

}

tuffle-config.js

  compilers: {
    solc: {
      version: "0.6.0",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  }

うーむ、普通にやっとるが、レベル高いな…

[Ethereum] DDTによる初めてのスマートコントラクト

$ truffle init
$ tree
.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
└── truffle-config.js

Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test

test/greeter_test.js

const GreeterContract = artifacts.require("Greeter");

contract("Greeter", () => {
	it("has been deployed successfully", async() => {
		const greeter = await GreeterContract.deployed();
		assert(greeter, "contract was not deployed");
	});
});

$ sudo truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-60133-1nsib01.f2gyk
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Error: Could not find artifacts for Greeter from any sources

contracts/Greeter.sol

pragma solidity >= 0.4.0 < 0.7.0;

contract Greeter {
	
}

$ truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Greeter.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-60435-1cj02xv.58fvg
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Contract: Greeter
1) has been deployed successfully
> No events were emitted

truffle testを実行するたびにコントラクトをコンパイルしてテストネットワークにデプロイする
ネットワークに追加するにはマイグレーションを作成する必要がある

migrations/2_deploy_greeter.js

const GreeterContract = artifacts.require("Greeter");

module.exports = function(deployer){
	deployer.deploy(GreeterContract);
}

$ truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Greeter.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-63614-1lnqpgc.prxq
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Contract: Greeter
✓ has been deployed successfully

1 passing (42ms)

contactをデプロイすると、テストをパスする

[Ethereum] 開発環境の準備

イーサリアムクライアントとNode.jsを使う
Node.jsはTuffle用のJS環境
ブロックチェーンとのやりとりはJSON-RPCを使う
今回はParityを使う

### Parityのインストール(ubuntu)

$ bash <(curl https://get.parity.io -L)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: get.parity.io

あれ…

### Parityのインストール(ubuntu)
$ sudo apt update
$ sudo apt install snapd
$ sudo snap install parity
parity v2.7.2 from Parity DevOps (devops-parity) installed

動作テスト
$ parity –chain=goerli
2021-12-13 02:44:58 UTC Starting Parity-Ethereum/v2.7.2-stable-2662d19-20200206/x86_64-unknown-linux-gnu/rustc1.41.0
2021-12-13 02:44:58 UTC Keys path /home/vagrant/snap/parity/16707/.local/share/io.parity.ethereum/keys/goerli
2021-12-13 02:44:58 UTC DB path /home/vagrant/snap/parity/16707/.local/share/io.parity.ethereum/chains/goerli/db/b1d518969eab529d
2021-12-13 02:44:58 UTC State DB configuration: fast
2021-12-13 02:44:58 UTC Operating mode: active
2021-12-13 02:44:59 UTC Configured for Görli Testnet using Clique engine

### MetaMask
JSON-RPCを通じてブロックチェーンのやり取りをする
12単語のハーモニックを格納できる

### node.js
$ curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
$ sudo bash nodesource_setup.sh
$ sudo apt install nodejs
$ node -v
v14.18.2

### Truffle Suite
$ npm install -g truffle@5.1.31
// npm install -g truffle

### Ganache
自分専用のブロックチェーンであり、JSON-RPCサーバを実行する

なんだこれえええええええええええええ

[Ethereum] 基礎

– EVM上で動く 
– Solidityはスマートコントラクトの開発によく使われている
– イーサリアムが評価されたのはスマートコントラクトをデプロイ・実行するためのプラットフォームを提供した為
– 世界中のイーサリアムノードで接続している
– パブリックイーサリアムネットワークに接続するには、ブルーノード(信頼性の高いIP)のリストがある
– フォークした場合、最も長いチェーンが勝つ
– Proof-of-stake: Ethereumを提供する
– トランザクション手数料をガスと言う
– トランザクションの処理は13秒に1つ程度
– メモリプールが起きた場合、高いガスを払うと、処理される
– メモリプールに複数のトランザクションが含まれている場合、ブロック作成者はナンスによってトランザクションを決める
– チェーンに新しいブロックが追加されてからトランザクションが確定
– ハードフォークを行なうときは議論になり、2016年のハードフォークで以前のプロトコルをイーサリアムクラシックと呼ぶ
– 1Gweiは10億ウェイで1イーサ
– プアブリックイーサリアムネットワークはmainnet、ステージング環境はtestnetでfaucetという無料配布の仕組みがある
– EVMのオペコードはPUSH1、MLOADといった命令があり、ガス費用が割り当てられる
– gasPriceを設定することができる フロントランニングでgasPriceを設定する
– gas属性とgasPrice属性が含まれていないといけない

### アカウント
– 基本的トランザクションはEOA間でのイーサ送金

### コントラクト
オブジェクト指向スタイル、 状態変数と関数
読み取り変数をpureとview

### ブロック作成者とトランザクション
gasPrice, origin, data, sender, sig, value, number, timestamp, blockhash, difficulty, gaslimit, coinbase
ブロック作成者はトランザクションの順序を操作できる

### トランザクション署名
秘密鍵、暗号署名はMetaMaskというウォレットソフトウェアに任せる
nonce, gasPrice, gas, to, value, data, chainId

### トークン
所有権を意味する

– ERC-20
相互に交換可能
totalSupply(), balanceOf(address _owner), transfer(address _to, unit256 _value), transferFrom(address _from, address _to, unit256 _value), approve(address _spender, unit256 _value), allowance(address _owner, address _spender)

– ERC-721
互いに異なっているトークン
balanceOf(address _owner), ownerOf(unit256 _tokenId), safeTranferFrom(address _from, address _to, unit256, _token_Id, bytes data), safeTranferFrom(address _from, address _to, unit256 _tokenId), tranferFrom(address _from, address _to, unit256 _tokenId), approve(address _approved, unit256 _tokenId), setApprovalForAll(address _operator, bool _approved), getApproved(unit256 _tokenId), isApprovedForAll(address _owner, address _operator)

– サプライチェーン
生産の条件やルートなどが記載される

### 永続的な記録
航空日誌を記録する など

チェーン上に記録できるのは、色々な機能としてできそう