# ZK Playground Homework 0
Link: https://hackmd.io/@ChiHaoLu/ZKPlayground-HW0
## Prerequisite
```bash
npm i -g eth-cli
```
## Problems
```bash
eth address:random > test_account.json
export ETH_CLI_PRIVATE_KEY=(cat test_account.json | jq '.privateKey' -r)
```
### Problem 1
```bash
eth transaction:send --to 0x847FB490b9255758738c1DBddD9E3049E9bC86c8 -n goerli --value 1000000000000000
```
### Problem 2
```
MACI
```
### Problem 3
```bash
eth method:hash 'claim(uint256)' # => 379607f5
# generate test ABI with solc
solcjs test.sol --abi
# Encode the argument with ABI
eth method:encode --goerli test_sol_test.abi 'claim(1)' # => 0x379607f50000000000000000000000000000000000000000000000000000000000000001
eth transaction:send --to 0x847FB490b9255758738c1DBddD9E3049E9bC86c8 -n goerli --data 0x379607f50000000000000000000000000000000000000000000000000000000000000001
```
### Problem 4
```bash
eth abi:add zk test_sol_test.abi
```
:::info
#### :bulb: 關於 contract read public arrray variable
原本是寫 `eth contract:call -n goerli zk@0x847FB490b9255758738c1DBddD9E3049E9bC86c8 'hashes(0)'` 一個一個拿,原因是 solidity 自動產生的 getter 會避免 gas costs(array 元素可能很多)
> If you have a public state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism exists to avoid high gas costs when returning an entire array
> https://docs.soliditylang.org/en/v0.8.4/contracts.html#getter-functions
> 也可以直接算就好了 https://emn178.github.io/online-tools/keccak_256.html
:::
```javascript
const keccak256 = require('keccak256');
const txs = [
'zkpenguin', // 0
'zkpancake', // 1
'zkpolice', // 2
'zkpig', // 3
'zkplayground', // 4
'zkpigeon', // 5
'zkpoison', // 6
];
const simpleHash = (a, b) => {
// compare string hex value
const intA = parseInt(a, 16);
const intB = parseInt(b, 16);
const concatedString = intA < intB ? a + b : b + a;
return keccak256(Buffer.from(concatedString, 'hex')).toString('hex');
};
const hashes = txs.map((tx) => keccak256(tx).toString('hex'));
// hash(hash(zkpig) <-> hash(zkpigeon))
const a = simpleHash(hashes[3], hashes[5]);
// hash(zkpoison)
const b = hashes[6];
const c = simpleHash(a, b);
// hash(hash(zkplayground) <-> hash(zkpenguin))
const d = simpleHash(hashes[4], hashes[0]);
// hash(hash(zkpancake) <-> hash(zkpolice))
const e = simpleHash(hashes[1], hashes[2]);
// d + e
const f = simpleHash(d, e);
const root = simpleHash(c, f);
// making proof path for zkplayground
const proof = [
hashes[0], // zkpenguin
// zkpancake <-> zkpolice
e,
c,
];
console.log('proof', proof);
console.log('root', root);
// generate function argument
console.log(JSON.stringify(proof.map((hash) => '0x' + hash)));
// root should be e2de7e936cd2e3b398a5b5b89726a8d72148b93050d271cf91ffec3cc5598577
if (
root === 'e2de7e936cd2e3b398a5b5b89726a8d72148b93050d271cf91ffec3cc5598577'
) {
console.log('root is correct');
} else {
console.error('root is incorrect');
}
```
```bash
eth contract:call -n goerli zk@0x847FB490b9255758738c1DBddD9E3049E9bC86c8 'merkleProof(["0x2098ddd01d6035049de112333af26442bb3009ea06b6df66fccfadf8adee9914","0xb4435d3d2bb4863bffe2dd7c4a217641efe9da99b177cef8693fe26910a2bf04","0x7c8d8e6486e95d2eaff942ec8eb9b732d53596cb06548b62ff4841438a25a5d4"])'
```
好!

## Test contract for generating ABI
```bash
npm i -g solc # skip if already installed
solcjs test.sol --abi
eth abi:add zk test_sol_test.abi
# if created
eth abi:update zk test_sol_test.abi
```
16 年開始接觸到以太坊,研究智能合約, 曾主導 NFT 項目發行與架構設計,本業是 Sass 新創軟體工程師,因為很喜歡研究 Computer Science,之前透過網路資源學習過 ZKP 相關理論知識,也自學 circom 相關知識與撰寫程式經驗,但尚有許多理論和技術細節並不熟悉,也想透過這次過程,研究更多 ZKP 相關的知識。
```solidity
// test.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
contract test {
bytes32[] public hashes;
function claim(uint256 _amountInFinney) public payable {}
function merkleProof(bytes32[] memory proof) public {}
}
```
### JS code of HW4
- [merkle-tree-practice/index.js at main · moojing/merkle-tree-practice (github.com)](https://github.com/moojing/merkle-tree-practice/blob/main/index.js)