---
# System prepended metadata

title: '區塊鏈 16,23,30-Sep-2022,'
tags: [blockchain]

---

# 區塊鏈 16,23,30-Sep-2022,

###### tags: `blockchain`

### jamboard

## https://jamboard.google.com/d/1s5ImoKlKkBXVWlap3UAz3SANHHAIth0VQbnU6QQc2rU/edit?usp=sharing

## 下載ganache的戰機
### https://trufflesuite.com/ganache/
### `10:30-10:40` break

## https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn
## https://metamask.io/

## https://github.com/ipfs/ipfs
## https://blockcast.it/2022/03/21/what-to-expect-after-the-ethereum-merge/

## 0x ba c5 2F 94 C4 67 85 07 88 4F 26 50 c9 10 43 e0 f3 3F 42 42

## https://github.com/ethereum/solidity


## http://remix.ethereum.org/

![](https://i.imgur.com/RTGpBB5.png)

# 4_Demo1.sol

```solidity=
// SPDX-License-Identifier: GPL-3.0
pragma solidity = 0.6.8;
contract Demo1 {

}

```

![](https://i.imgur.com/dzLYZNs.png)


# Demo1.sol


```solidity

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo1 {
    string public message;
    constructor(string memory initMessage) {
        message = initMessage;
    }
    function setMessage(string memory newMessage) public {
        message = newMessage;
    }
    function getMessage() public view returns(string memory) {
        return message;
    }
}


    


```
![](https://i.imgur.com/mhgycwj.png)

# break 3:40-3:50

#  https://iancoleman.io/bip39/#english

# Demo2
```solidity=

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo2 {
    function getrResult(uint a, uint b) public pure returns (string memory){
        return integerToString(a+b);
    }
    function integerToString(uint i) internal pure returns(string memory){
      if (i==0){
          return "0";
      }
      // 算出有幾位數
      uint j=i;
      uint len;
      while (j!=0){
          len++;
          j/=10;
      }
      bytes memory bstr = new bytes(len);
      uint k = len-1;
      while(i != 0){
          bstr[k--]=bytes1(uint8(48+(i%10)));
          i /= 10;
      }
      return string(bstr);
    }
}
```

![](https://i.imgur.com/XDedJj7.png)


# Demo3

```solidity=

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo3 {
    function arrayDemo1() public pure returns (uint256){
        uint len= 7;
        uint[] memory a = new uint[](len);
        return a.length;
    }
}
```

# download node.JS if not
## https://nodejs.org/en/
# download visual studio code if not
## https://code.visualstudio.com/
## 16.16, 16.17 or 18.X 都可以
## 打開http://remix.ethereum.org/

# 6_demo3.sol

```solidity!
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo3 {
    function arrayDemo1() public pure returns (uint256){
        uint len= 7;
        uint[] memory a = new uint[](len);
        return a.length;
    }
    function arrayDemo2(uint length) public pure returns(uint256) {
        uint[] memory a = new uint[](length);
        return a.length;
    }
    function arrayDemo3() public pure returns(uint256) {
        uint[7] memory a;
        return a.length;
    }
    function arrayDemo4(uint index) public pure returns(uint256) {
        uint[] memory a = new uint[](7);
        a[6]=7;
        a[5]=6;
        a[4]=5;
        a[3]=4;
        a[2]=3;
        a[1]=2;
        a[0]=1;
        return a[index];
    }
    function arrayDemo5(uint index) public pure returns(uint256) {
        uint[7] memory a;
        a[6]=7;
        a[5]=6;
        a[4]=5;
        a[3]=4;
        a[2]=3;
        a[1]=2;
        a[0]=1;
        return a[index];
    }
    function arrayDemo6() public pure returns(uint[7] memory) {
        uint[7] memory a;
        a[6]=7;
        a[5]=6;
        a[4]=5;
        a[3]=4;
        a[2]=3;
        a[1]=2;
        a[0]=1;
        return a;
    }
    function arrayDemo7() public pure returns(uint[] memory) {
        uint[] memory a = new uint[](7);
        a[6]=7;
        a[5]=6;
        a[4]=5;
        a[3]=4;
        a[2]=3;
        a[1]=2;
        a[0]=1;
        return a;
    }

}
```
![](https://i.imgur.com/eqAxaSM.png)


# 7_Demo4.sol
```solidity!
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo4 {
    uint256[] members1 = new uint256[](5);
    function arrayTest1() public {
        members1[0]=2;
        members1[1]=4;
        members1[2]=6;
        members1[3]=8;
        members1[4]=10;
    }
    function arrayTest2() public view returns(uint256[] memory){
        return members1;
    }
    function arrayTest3(uint d) public {
        members1.push(d);
    }
    
}
```

# 8_Demo5.sol
```solidity!

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo5 {
    enum StarbuckSize {SHORT, TALL, GRANDE, VENTI, TRENTA}
    StarbuckSize size;
    StarbuckSize constant defaultSize=StarbuckSize.TALL;
    StarbuckSize size2 = StarbuckSize.GRANDE;
    function getSize1() public view returns (StarbuckSize) {
        return size;
    }
    function getSize2() public pure returns (StarbuckSize) {
        return defaultSize;
    }
    function getSize3() public view returns (StarbuckSize) {
        return size2;
    }
    function setSize1(StarbuckSize s)public {
        size = s;
    }
    // function setSize2(StarbuckSize s) public {
    //     defaultSize = s;
    // }
    function getSize4() public view returns (uint8){
        return uint8(size);
    }
}
```



![](https://i.imgur.com/kBpLs3l.png)

# 9_Demo6.sol
```solidity!

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo7 {
    mapping(address=>uint)public balances;
    function updateBalance(uint newBalance) public {
        balances[msg.sender] = newBalance;
    }
    function getBalance() public view returns (uint) {
        return balances[address(this)];
    }
    function setContractBalance(uint v) public {
        balances[address(this)]=v;
    }
}
```

![](https://i.imgur.com/8QVmLVo.png)


![](https://i.imgur.com/fOmeJLD.png)

![](https://i.imgur.com/tdVNrjW.png)

# 11_demo8.sol
```solidity=

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo8{
    function getMultiReturn() public pure returns(uint256 product, uint256 sum) {
        uint a=3;
        uint b=5;
        return (a*b, a+b);
    }
    function getMultiReturn2() public pure returns(uint256 product, uint256 sum){
        uint a=3;
        uint b=5;
        product = a*b;
        sum = a+b;
    }
}

```

# 12_demo9.sol
```solidity!
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
contract Demo9 {
    address owner;
    constructor() {
        owner = msg.sender;
    }
    modifier onlyOwner {
        require(msg.sender==owner);
        _;
    }
    modifier costs(uint256 price) {
        if (msg.value >= price) {
            _;
        }
    }
}
contract Register is Demo9 {
    mapping(address => bool) public registeredAddress;
    uint public price;
    constructor(uint initPrice) {
        price = initPrice;
    }
    function register() public payable costs(price) {
        registeredAddress[msg.sender] = true;
    }
    function changePrice(uint256 _price) public onlyOwner {
        price = _price;
    }
}
```

![](https://i.imgur.com/zDfjLLa.png)


![](https://i.imgur.com/4rOEFJS.png)


![](https://i.imgur.com/j2CqD4J.png)


![](https://i.imgur.com/UmeaDug.png)

![](https://i.imgur.com/hudATy6.png)

![](https://i.imgur.com/ftLEk8p.png)

# 13_Demo10.sol
```solidity=

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;
contract Demo10 {
    string[] public myArray;
    constructor() {
        myArray.push("Hi");
        myArray.push("Hello world");
    }
    function getArray() public view returns (string[] memory) {
        return myArray;
    }
}

```

# truffle install
# https://github.com/git-for-windows/git/releases/download/v2.37.3.windows.1/Git-2.37.3-64-bit.exe
```
npm uninstall -g truffle
npm uninstall -g ganache-cli
npm install -g truffle
npm install -g npm@8.19.2
npm list -g
npm install -g ganache-cli
truffle --version
ganache-cli --version
```
# 參考的結果是
```
C:\Users\user>truffle --version
Truffle v5.5.31 (core: 5.5.31)
Ganache v7.4.3
Solidity v0.5.16 (solc-js)
Node v16.16.0
Web3.js v1.7.4

C:\Users\user>ganache-cli --version
Ganache CLI v6.12.2 (ganache-core: 2.13.2)
```

```
code .
```
ctrl+k,o

# https://github.com/github/gitignore/blob/main/Node.gitignore

# Extensions
* Name: Git Graph
Id: mhutchie.git-graph
Description: View a Git Graph of your repository, and perform Git actions from the graph.
Version: 1.30.0
Publisher: mhutchie
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph
* Name: solidity
Id: JuanBlanco.solidity
Description: Ethereum Solidity Language for Visual Studio Code
Version: 0.0.140
Publisher: Juan Blanco
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity

![](https://i.imgur.com/cT7s9rR.png)

```
npm init -y
truffle init -y

```
# template的樣本
```
Try our scaffold commands to get started:
  $ truffle create contract YourContractName # scaffold a contract
  $ truffle create test YourTestName         # scaffold a test

http://trufflesuite.com/docs
```
# https://trufflesuite.com/ganache/
```javascript!
  compilers: {
    solc: {
      version: "0.5.16",      // 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"
      }
    }
  },
```
# 完整的
```javascript=
/**
 * Use this file to configure your truffle project. It's seeded with some
 * common settings for different networks and features like migrations,
 * compilation, and testing. Uncomment the ones you need or modify
 * them to suit your project as necessary.
 *
 * More information about configuration can be found at:
 *
 * https://trufflesuite.com/docs/truffle/reference/configuration
 * 
 * Hands-off deployment with Infura
 * --------------------------------
 *
 * Do you have a complex application that requires lots of transactions to deploy?
 * Use this approach to make deployment a breeze 🏖️:
 *
 * Infura deployment needs a wallet provider (like @truffle/hdwallet-provider)
 * to sign transactions before they're sent to a remote public node. 
 * Infura accounts are available for free at 🔍: https://infura.io/register
 *
 * You'll need a mnemonic - the twelve word phrase the wallet uses to generate
 * public/private key pairs. You can store your secrets 🤐 in a .env file. 
 * In your project root, run `$ npm install dotenv`. 
 * Create .env (which should be .gitignored) and declare your MNEMONIC 
 * and Infura PROJECT_ID variables inside.
 * For example, your .env file will have the following structure:
 * 
 * MNEMONIC = <Your 12 phrase mnemonic>
 * PROJECT_ID = <Your Infura project id>
 * 
 * Deployment with Truffle Dashboard (Recommended for best security practice)
 * --------------------------------------------------------------------------
 * 
 * Are you concerned about security and minimizing rekt status 🤔?
 * Use this method for best security:
 * 
 * Truffle Dashboard lets you review transactions in detail, and leverages 
 * MetaMask for signing, so there's no need to copy-paste your mnemonic. 
 * More details can be found at 🔎: 
 * 
 * https://trufflesuite.com/docs/truffle/getting-started/using-the-truffle-dashboard/
 */

// require('dotenv').config();
// const { MNEMONIC, PROJECT_ID } = process.env;

// const HDWalletProvider = require('@truffle/hdwallet-provider');

module.exports = {
  /**
   * Networks define how you connect to your ethereum client and let you set the
   * defaults web3 uses to send transactions. If you don't specify one truffle
   * will spin up a managed Ganache instance for you on port 9545 when you
   * run `develop` or `test`. You can ask a truffle command to use a specific
   * network from the command line, e.g
   *
   * $ truffle test --network <network-name>
   */

  networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache, geth, or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 7545,            // Standard Ethereum port (default: none)
     network_id: "*",       // Any network (default: none)
    },
    //
    // An additional network, but with some advanced options…
    // advanced: {
    //   port: 8777,             // Custom port
    //   network_id: 1342,       // Custom network
    //   gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
    //   gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
    //   from: <address>,        // Account to send transactions from (default: accounts[0])
    //   websocket: true         // Enable EventEmitter interface for web3 (default: false)
    // },
    //
    // Useful for deploying to a public network.
    // Note: It's important to wrap the provider as a function to ensure truffle uses a new provider every time.
    // goerli: {
    //   provider: () => new HDWalletProvider(MNEMONIC, `https://goerli.infura.io/v3/${PROJECT_ID}`),
    //   network_id: 5,       // Goerli's id
    //   confirmations: 2,    // # of confirmations to wait between deployments. (default: 0)
    //   timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
    //   skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },
    //
    // Useful for private networks
    // private: {
    //   provider: () => new HDWalletProvider(MNEMONIC, `https://network.io`),
    //   network_id: 2111,   // This network is yours, in the cloud.
    //   production: true    // Treats this network as if it was a public net. (default: false)
    // }
  },

  // Set default mocha options here, use special reporters, etc.
  mocha: {
    // timeout: 100000
  },

  // Configure your compilers
  compilers: {
    solc: {
      version: "0.5.16",      // 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"
      }
    }
  },

  // Truffle DB is currently disabled by default; to enable it, change enabled:
  // false to enabled: true. The default storage location can also be
  // overridden by specifying the adapter settings, as shown in the commented code below.
  //
  // NOTE: It is not possible to migrate your contracts to truffle DB and you should
  // make a backup of your artifacts to a safe location before enabling this feature.
  //
  // After you backed up your artifacts you can utilize db by running migrate as follows:
  // $ truffle migrate --reset --compile-all
  //
  // db: {
  //   enabled: false,
  //   host: "127.0.0.1",
  //   adapter: {
  //     name: "sqlite",
  //     settings: {
  //       directory: ".db"
  //     }
  //   }
  // }
};

```

# lab1.sol
```solidity=
pragma solidity ^0.5.16;

contract GMR {
    address public manager;
    constructor() public {
        manager = msg.sender;
    }
}
```

# build with command line
```
truffle compile
```
![](https://i.imgur.com/KbcLaJW.png)

![](https://i.imgur.com/gS7g1XY.png)

```
truffle create migration GMR
```

# 1_g_m_r.js
```javascript=
const GMR = artifacts.require("GMR")
module.exports = function (_deployer) {
  _deployer.deploy(GMR);
};

```
# 部署
```
truffle deploy
```

# 檢視solcjs
# 進入到contracts的目錄
```
solcjs --version
solcjs --abi lab1.sol
```

# mkdir lab2_solidity_test
```
copy lab1_solidity_intro\.gitignore lab2_solidity_test

```
# 打開vs code後
```
npm init -y
truffle init -y
```
# Call.sol
```solidity
pragma solidity ^0.5.16;
contract Chat {
    string public message;
    constructor (string memory initMessage) public {
        message = initMessage;
    }
    function setMessage(string memory newMessage) public {
        message = newMessage;
    }
    function getMessage() public view returns (string memory) {
        return message;
    }
}


```
# 2_call.js
```javascript=

const Chat = artifacts.require("Chat");
module.exports = function (_deployer) {
  _deployer.deploy(Chat, "Hi, I am truffle")
};



```
# npm install mocha
# .\Room.js
```javascript=
class Room {
    constructor() {
        console.log("**創建了一個Room**")
    }
    open() {
        return "door open, welcome"
    }
    close() {
        return "door close,bye bye"
    }
}
module.exports = Room
```

# .\test\Room.test.js


https://mochajs.org/

```javascript
const Room = require("../Room")
const assert = require("assert")
it("this is my first test", () => {
    console.log("要執行第一個測試~!")
})
it("this is my second test", () => {
    console.log("這是我的第二個測試")
})
```

# node_modules\.bin\mocha test
```javascript=
  "scripts": {
    "test": "mocha"
  },
```
# npm run test
# alt+shift+F 排列程式碼

# BC.test.js
```javascript
it("寫在其它的檔的測試", () => {
    console.log("test something else...")
})

```
# Room.test.js
```javascript
const Room = require("../Room")
const assert = require("assert")
before("準備工作", () => {
    console.log("準備資料")
})
beforeEach("派送資料", () => {
    console.log("[p]指派該份資料到測試")
})
afterEach("收集資料", () => {
    console.log("[c]收集資料並且清理環境")
})
after("最後收尾", () => {
    console.log("最後收尾")
})
it("this is my first test", () => {
    console.log("要執行第一個測試~!")
})
it("this is my second test", () => {
    console.log("這是我的第二個測試")
})
describe("測試Room的這個類別", () => {
    let r1;
    before("prepare r1",()=>{
        r1 = new Room();
    })
    it("test1, 測試門會開", () => {
        assert.strictEqual(r1.open(), "door open, welcome")
    })
    it("test2, 測試門會關", () => {
        assert.strictEqual(r1.close(), "door close,bye bye")
    })
})
```
# day2的程式碼請見:
## https://drive.google.com/file/d/1VwJMoBEAs91iqLl9OkZILDBLYvHbHQ_7/view?usp=sharing


# day3
```
cd lab2_solidity_test
```
## npm run test
## node_modules\.bin\mocha test
## 執行某一個特定的檔案
### `npm run test -- test\BC.test.js`

# `my.test.web3.js`
```javascript=
describe("test web3 alone", () => {
    it("get web3 environment", () => {

    })
})
```
## npm install 連至區塊鏈需要的內容
```
npm install web3
npm install ganache-cli
```
## 修改my.test.web3.js
```javascript
const assert = require("assert")
const ganache = require("ganache-cli")
const Web3 = require("web3")
const web3 = new Web3(ganache.provider())
beforeEach(() => {
    //console.log("web3=", web3)
    web3.eth.getAccounts().then((accounts)=>{
        console.log("帳號這時候才來")
        console.log(accounts)
    })
    //console.log("result=", result)
})
describe("test web3 alone", () => {
    it("get web3 environment", () => {
        console.log("執行測試")
    })
})
```

## npm run test -- test\my.web3.test.js

# my2.web3.test.js
```javascript
const assert = require("assert")
const ganache = require("ganache-cli")
const Web3 = require("web3")
const web3 = new Web3(ganache.provider())
let accounts;
beforeEach(async () => {
    accounts = await web3.eth.getAccounts();
})
describe("test web3 alone", () => {
    it("get web3 environment", () => {
        console.log("執行測試")
        console.log("取得第一個帳號", accounts[0])
    })
})
```
## npm run test -- test\my2.web3.test.js
### npm install chai chai-as-promised

## contract.test.js
```javascript=
const { default: Web3 } = require("web3")

contract("測試合約", accounts => {
    it("1.取得帳戶", () => {
        console.log("第一個帳戶是:", accounts[0])
    })
    it("2.取得餘額", async () => {
        // 直接送一個web3
        const balance = await web3.eth.getBalance(accounts[0]);
        console.log("餘額是:", balance)
    })
})

```

## truffle test -- .\test\contract.test.js
## !!
## 修改Call.sol ==> Chat.sol
```javascript=
const Chat = artifacts.require("../contracts/Chat.sol")
let chat;
beforeEach(async () => {
    chat = await Chat.deployed()
    console.log("部署好合約:")
})
contract("與合約互動", accounts => {
    it("取得初始化的值", async () => {
        console.log("作測試")
        const message = await chat.getMessage();
        console.log("合約初始值是:", message)
    })
    it("設值再把值取回", async () => {
        await chat.setMessage("修改到其它值")
        const m1 = await chat.getMessage();
        console.log("修改完的結果是", m1)
        const m2 = await chat.message();
        console.log("使用變數生成的函數結果是", m2)
    })
})
```
```
mkdir lab3_metacoin
cd lab3_metacoin
truffle unbox metacoin
```

# README.md
```
truffle test .\test\TestMetaCoin.sol
```

![](https://i.imgur.com/EM8zbYj.png)

![](https://i.imgur.com/j0dbQBC.png)

![](https://i.imgur.com/tX7PdLs.png)

```javascript=
    development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 7545,            // Standard Ethereum port (default: none)
     network_id: "5777",       // Any network (default: none)
    },
```

# commands
```
accounts
accounts[0]
```

![](https://i.imgur.com/cGu7ifw.png)
```
web3
web3.eth
```
```
deploy 
let instance = await MetaCoin.deployed()
typeof instance
let accounts = await web3.eth.getAccounts()
accounts[0]
let balance = await instance.getBalance(accounts[0])
 balance
 balance+balance
 balance.toNumber()+balance.toNumber()
let balanceInEther = await instance.getBalanceInEth(accounts[0])
typeof balanceInEther
balanceInEther.toNumber()
balanceInEther.toNumber()*5
instance.sendCoin(accounts[1],500)
let b1 = await instance.getBalance(accounts[0])
b1.toNumber()
let b2 = await instance.getBalance(accounts[1])
b2.toNumber()
```
# https://drive.google.com/file/d/1yvxxHuBTgjD6INyZbhz3q4w45I_uDnAx/view?usp=sharing

```solidity
pragma solidity ^0.5.16;

contract GMR {
    address public manager;
    address[] public players;
    constructor() public {
        manager = msg.sender;
    }
    function enterGame() public payable {
        players.push(msg.sender);
    }
}
```


![](https://i.imgur.com/aMtKtfW.png)


![](https://i.imgur.com/SEuD2y3.png)


# 修改程式加上限制
```javascript=
pragma solidity ^0.5.16;

contract GMR {
    address public manager;
    address[] public players;
    constructor() public {
        manager = msg.sender;
    }
    function enterGame() public payable {
        require(msg.value>0.01 ether);
        players.push(msg.sender);
    }
}
```

![](https://i.imgur.com/CfcYhFI.png)

# https://eth-converter.com/

![](https://i.imgur.com/uZunKTJ.png)

```solidity
pragma solidity ^0.5.16;

contract GMR {
    address public manager;
    address payable[] public players;
    constructor() public {
        manager = msg.sender;
    }
    function enterGame() public payable {
        require(msg.value>0.01 ether);
        players.push(msg.sender);
    }
    function getContractBalance() public view returns (uint) {
        return address(this).balance;
    }
    modifier restricted() {
        require(msg.sender==manager);
        _;
    }
    function payMoneyToPlayer() public restricted {
        //require(msg.sender==manager);
        uint winnerIndex = chooseByTime();
        players[winnerIndex].transfer(getContractBalance());
        players = new address payable[](0);
    }
    function chooseByTime() private view returns (uint) {
        uint result = block.timestamp%players.length;
        return result;
    }
    function getCurrentPlayers() public view returns (address payable[] memory) {
        return players;
    }
}
```

![](https://i.imgur.com/kgqEzQ4.png)

# npm install mocha chai chai-as-promised

## GMR.test.js

```javascript

const GMR = artifacts.require("../contracts/GMR.sol");

let gmr;
beforeEach(() => {

})
contract("lab1 GMR testing:", accounts => {
    it("部署完檢查帳號", () => {
        console.log("accounts=",accounts[0]);
    })
})


```
# npm list -g

![](https://i.imgur.com/SbPh9sd.png)


```javascript=
    test: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none) 
    },
    development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 7545,            // Standard Ethereum port (default: none)
     network_id: "*",       // Any network (default: none)
    },

```

## `truffle test --network test test\GMR.test.js`
```javascript
const GMR = artifacts.require("../contracts/GMR.sol");
const assert = require("assert");


let gmr;
beforeEach(async () => {
    //gmr = await GMR.deployed();
    gmr = await GMR.new();
    console.log("GMR is fresh deployed");
})
contract("lab1 GMR testing:", accounts => {
    it("部署完檢查合約地址", () => {
        //console.log("accounts=", accounts[0]);
        assert.ok(gmr.address);
    })
    it("管理者應該是第一個帳戶", async () => {
        console.log("accounts[0]=", accounts[0]);
        const manager = await gmr.manager();
        console.log("manager=", manager);
        assert.strictEqual(accounts[0], manager);
    })
    it("進入遊戲", async () => {
        await gmr.enterGame({
            from: accounts[0],
            value: web3.utils.toWei("0.02", "ether")
        });
        const players = await gmr.getCurrentPlayers();
        console.log("目前使用者是:", players);
        assert.strictEqual(players[0], accounts[0]);
        assert.strictEqual(1, players.length);
    })
    it("多筆玩家", async () => {

        const joiningPlayers = [accounts[1], accounts[2], accounts[3], accounts[4]];
        for (let p of joiningPlayers) {
            await gmr.enterGame({ from: p, value: web3.utils.toWei("0.02", "ether") })
        }
        const players = await gmr.getCurrentPlayers();
        console.log("目前使用者是:", players);
        assert.strictEqual(4, players.length);
        assert.strictEqual(accounts[1], players[0]);
        assert.strictEqual(accounts[2], players[1]);
        assert.strictEqual(accounts[3], players[2]);
        assert.strictEqual(accounts[4], players[3]);
    })
})
```
# GMR.fail.test.js
```javascript
const GMR = artifacts.require("../contracts/GMR.sol");
//const assert = require("assert");


let gmr;
beforeEach(async () => {
    gmr = await GMR.deployed();
    //gmr = await GMR.new();
    console.log("GMR is fresh deployed");
})
contract("GMR不正確時的檢查", accounts => {
    it("入場費不夠", async () => {
        try {
            await gmr.enterGame({
                from: accounts[0],
                value: 300
            })
            assert(false);
        } catch (err) {
            assert.isAbove(err.message.search("VM Exception while processing transaction"),
                -1, "應該要發生的是VM的錯誤");
        }
    })

})
```

![](https://i.imgur.com/6RHcZx2.png)

## mkdir lab4_cac
## cd lab4_cac
## copy ..\lab1_solidity_intro\.gitignore .
## code .
```
npm init -y
truffle init -y
git init

```

# cac.sol
```solidity=
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;

contract CAC {
    address public manager;
    uint256 public minimumFund;
    address[] public approvers;

    constructor(uint256 minimum) public {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        approvers.push(msg.sender);
    }
}


```
# 1_init_cac.js
```javascript

const CAC = artifacts.require("CAC")

module.exports = function(deployer){
    deployer.deploy(CAC, 500);
}
```
```javascript
    development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 9545,            // Standard Ethereum port (default: none)
     network_id: "*",       // Any network (default: none)
    },
```

# truffle develop
## truffle deploy
## truffle develop --network development
## deploy
## deploy --reset
```
let cac1 = await CAC.deployed()
typeof cac1
cac1
cac1.manager()
await cac1.manager()
cac1.minimumFund()
await cac1.minimumFund()
let cac1_mf = await cac1.minimumFund()
cac1_mf.toNumber()
(await cac1.minimumFund()).toNumber()
```

![](https://i.imgur.com/SbZklPP.png)


## day3 完成的code

# https://drive.google.com/file/d/1L7A7GL-kL-7mvNLlhdpzqY0xrxLs7Dzu/view?usp=sharing

# Day4開始
## 使用LAB4_CAC
## 使用truffle-cli
## truffle develop
### 在truffle>
```
deploy
accounts
let cac1 = await CAC.deployed()
(await cac1.minimumFund()).toNumber()

```

## not enough
```
cac1.join({from:accounts[1], value:450})
```

## enough
```
cac1.join({from:accounts[1], value:550})
cac1.approvers(1)
accounts[1]
```

## CAC.sol
```solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;

contract CAC {
    struct SpendingRequest {
        string description;
        uint value;
        address vendorAccount;
        bool complete;
    }
    SpendingRequest[] public requests;
    address public manager;
    uint256 public minimumFund;
    address[] public approvers;
    
    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint256 minimum) public {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        approvers.push(msg.sender);
    }
}

```
# http://remix.ethereum.org/

## 16_Demo12.sol

```solidity=

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

contract Demo13 {
    int[] public myArray;
    constructor() {
        myArray.push(100);
    }
    function addSomething() public {
        myArray.push(200);
        myArray.push(300);
        int[] storage myArray2 = myArray;
        myArray2[0]=555;
    }
}

```
## 19_Demo15.sol
```solidity=
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

contract Demo14 {
    int[] public myArray;
    constructor() {
        myArray.push(100);
    }
    function addSomething() public {
        myArray.push(200);
        myArray.push(300);
        int[] memory myArray2 = myArray;
        myArray2[0]=555;
    }
}



```
## CAC.sol
```solidity=

// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;

contract CAC {
    struct SpendingRequest {
        string description;
        uint value;
        address vendorAccount;
        bool complete;
    }
    SpendingRequest[] public requests;
    address public manager;
    uint256 public minimumFund;
    address[] public approvers;

    function createRequest(string memory des,
    uint value, address vendor) public restricted  {
        SpendingRequest memory req = SpendingRequest({
            description:des,
            value:value,
            vendorAccount:vendor,
            complete:false
        });
        requests.push(req);
    }
    modifier restricted() {
        require(msg.sender == manager);
        _;
    }
    constructor(uint256 minimum) public {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        approvers.push(msg.sender);
    }
}



```


![](https://i.imgur.com/fEGV0eh.png)

```
migrate --reset
```
```
cac1.createRequest()
cac1 = await CAC.deployed()
cac1.createRequest("wash outer wall",1000,accounts[0])
cac1.requests(0)
cac1.createRequest("wash outer wall",1000,accounts[0],{from:accounts[1]})
```

# CAC.sol
```solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;

contract CAC {
    struct SpendingRequest {
        string description;
        uint value;
        address vendorAccount;
        bool complete;
        // change to mapping
        uint approvalCount;
        mapping(address=>bool) approvedUsers;
    }
    SpendingRequest[] public requests;
    address public manager;
    uint256 public minimumFund;
    // change to mapping
    mapping(address=>bool) public approvers;
    uint public approversCount;

    function createRequest(string memory des,
    uint value, address vendor) public restricted  {
        SpendingRequest memory req = SpendingRequest({
            description:des,
            value:value,
            vendorAccount:vendor,
            complete:false,
            approvalCount:0
        });
        requests.push(req);
    }
    modifier restricted() {
        require(msg.sender == manager);
        _;
    }
    constructor(uint256 minimum) public {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        //approvers.push(msg.sender);
        approvers[msg.sender] = true;
    }
}



```
# 重新檢驗
```
migrate --reset

cac1 = await CAC.deployed()
cac1.createRequest("wash outer wall",1000,accounts[0])
cac1.requests(0)
cac1.createRequest("wash outer wall",1000,accounts[0],{from:accounts[1]})
```

![](https://i.imgur.com/1EedFiV.png)

# CAC.sol
## 相容於0.76版
```solidity=
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

contract CAC {
    struct SpendingRequest {
        string description;
        uint256 value;
        address vendorAccount;
        bool complete;
        // change to mapping
        uint256 approvalCount;
        mapping(address => bool) approvedUsers;
    }
    uint256 numRequests;
    mapping(uint256 => SpendingRequest) public requests;
    address public manager;
    uint256 public minimumFund;
    // change to mapping
    mapping(address => bool) public approvers;
    uint256 public approversCount;

    function createRequest(
        string memory des,
        uint256 value,
        address vendor
    ) public restricted {
        SpendingRequest storage spendingRequest = requests[numRequests++];
        spendingRequest.description = des;
        spendingRequest.value = value;
        spendingRequest.vendorAccount = vendor;
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint256 minimum) {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        //approvers.push(msg.sender);
        approvers[msg.sender] = true;
        approversCount++;
    }

    function approvalRequest(uint256 index) public {
        SpendingRequest storage request = requests[index];
        require(approvers[msg.sender]);
        require(!request.approvedUsers[msg.sender]);
        request.approvalCount++;
        request.approvedUsers[msg.sender] = true;
    }
}



```
```
compile
migrate --reset
cac1 = await CAC.deployed()
cac1.createRequest("wash outer wall",1000,accounts[9])
cac1.requests(0)
```

![](https://i.imgur.com/cbM8Bb7.png)

![](https://i.imgur.com/sc2YsFb.png)

![](https://i.imgur.com/naEI4p1.png)

![](https://i.imgur.com/0rSPU1q.png)

![](https://i.imgur.com/iIdktdd.png)

![](https://i.imgur.com/H6bvJHd.png)

```
npm install mocha chai chai-as-promised
```

## package.json
```json
  "scripts": {
    "test": "mocha"
  },
```
## truffle develop
```javascript=
const assert = require("chai").assert;
const CAC = artifacts.require("CAC.sol");
let cac
const VM_ERROR_STRING = "VM Exception while processing transaction:"
beforeEach(async () => {
    //cac = await CAC.deployed();
    cac = await CAC.new(500);
})
contract("test CAC", (accounts) => {
    it("contract exist", async () => {
        assert(cac != null, "array should not be null")
        //console.log("cac address=", cac.address)
    })
    it("get minimum fund", async () => {
        const minimumFund = await cac.minimumFund();
        const v = minimumFund.toNumber();
        //console.log("type is", typeof v);
        // strict equal ===
        // equal ==
        assert.strictEqual(v, 500, "minimum fund should be 500");
    })
    it("get manager", async () => {
        const mgr = await cac.manager();
        console.log("mgr", typeof mgr);
        assert.strictEqual(mgr, accounts[0], "manager should be first account");
    })
    it("join, make request, and approve", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
    })
    it("join, make request, and approve twice", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.join({ from: accounts[1], value: 550 });
        await cac.join({ from: accounts[2], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        try {
            await cac.approvalRequest(0, { from: accounts[0] });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
    it("not enough fee", async () => {
        try {
            await cac.join({ from: accounts[0], value: 450 });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }
    })
    it("not approvers", async () => {
        await cac.createRequest("clean floor", 1000, accounts[9]);
        try{
            await cac.approvalRequest(0, { from: accounts[5] });
            assert(false)
        } catch(e){
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }
        
    })
})
```

# CAC (with payable vendor)
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

contract CAC {
    struct SpendingRequest {
        string description;
        uint256 value;
        address payable vendorAccount;
        bool complete;
        // change to mapping
        uint256 approvalCount;
        mapping(address => bool) approvedUsers;
    }
    uint256 numRequests;
    mapping(uint256 => SpendingRequest) public requests;
    address public manager;
    uint256 public minimumFund;
    // change to mapping
    mapping(address => bool) public approvers;
    uint256 public approversCount;

    function createRequest(
        string memory des,
        uint256 value,
        address payable vendor
    ) public restricted {
        SpendingRequest storage spendingRequest = requests[numRequests++];
        spendingRequest.description = des;
        spendingRequest.value = value;
        spendingRequest.vendorAccount = vendor;
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint256 minimum) {
        manager = msg.sender;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        //approvers.push(msg.sender);
        approvers[msg.sender] = true;
        approversCount++;
    }

    function approvalRequest(uint256 index) public {
        SpendingRequest storage request = requests[index];
        require(approvers[msg.sender]);
        require(!request.approvedUsers[msg.sender]);
        request.approvalCount++;
        request.approvedUsers[msg.sender] = true;
    }

    function executeRequest(uint256 index) public restricted {
        SpendingRequest storage request = requests[index];
        require(!request.complete);
        require(request.approvalCount > (approversCount / 2));
        request.vendorAccount.transfer(request.value);
        request.complete = true;
    }
}



```

# CAC2.test.js
```javascript=
const assert = require("chai").assert;
const CAC = artifacts.require("CAC.sol");
let cac
const VM_ERROR_STRING = "VM Exception while processing transaction:"
beforeEach(async () => {
    //cac = await CAC.deployed();
    cac = await CAC.new(500);
})
contract("test more CAC", (accounts) => {
    it("付款失敗", async () => {
        await cac.join({ from: accounts[0], value: 1000 });
        await cac.join({ from: accounts[1], value: 1000 });
        await cac.join({ from: accounts[2], value: 1000 });
        await cac.createRequest("clean floor", 888, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        try {
            await cac.executeRequest(0);
            assert(false);
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
    it("取得帳戶餘額", async () => {
        const amount1 = await web3.eth.getBalance(accounts[0]);
        console.log("餘額是", typeof amount1, amount1);
        const value = BigInt(amount1);
        console.log("value=", typeof value, value);
        console.log("轉成bigint可以作加減", value + 100n);
        console.log("轉成bigint可以作加減", value - 100n);
    })
    it("付款成功", async () => {
        await cac.join({ from: accounts[0], value: 1000 });
        await cac.join({ from: accounts[1], value: 1000 });
        await cac.join({ from: accounts[2], value: 1000 });
        await cac.createRequest("clean floor", 888, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        await cac.approvalRequest(0, { from: accounts[1] });
        const origBalance = await web3.eth.getBalance(accounts[9]);
        console.log("原本accounts[9]的餘額是", origBalance);
        await cac.executeRequest(0);
        const newBalance = await web3.eth.getBalance(accounts[9]);
        console.log("新accounts[9]的餘額是", newBalance);
        const remaining = BigInt(newBalance) - BigInt(origBalance);
        console.log("值是:", remaining);
        assert.strictEqual(BigInt(888), remaining, `值應該是${remaining}`);

    })
})
```

## 修改完的CAC.sol
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

contract CAC {
    struct SpendingRequest {
        string description;
        uint256 value;
        address payable vendorAccount;
        bool complete;
        // change to mapping
        uint256 approvalCount;
        mapping(address => bool) approvedUsers;
    }
    uint256 numRequests;
    mapping(uint256 => SpendingRequest) public requests;
    address public manager;
    uint256 public minimumFund;
    // change to mapping
    mapping(address => bool) public approvers;
    uint256 public approversCount;

    function createRequest(
        string memory des,
        uint256 value,
        address payable vendor
    ) public restricted {
        SpendingRequest storage spendingRequest = requests[numRequests++];
        spendingRequest.description = des;
        spendingRequest.value = value;
        spendingRequest.vendorAccount = vendor;
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint256 minimum,address creator) {
        manager = creator;
        minimumFund = minimum;
    }

    function join() public payable {
        require(msg.value > minimumFund);
        //approvers.push(msg.sender);
        approvers[msg.sender] = true;
        approversCount++;
    }

    function approvalRequest(uint256 index) public {
        SpendingRequest storage request = requests[index];
        require(approvers[msg.sender]);
        require(!request.approvedUsers[msg.sender]);
        request.approvalCount++;
        request.approvedUsers[msg.sender] = true;
    }

    function executeRequest(uint256 index) public restricted {
        SpendingRequest storage request = requests[index];
        require(!request.complete);
        require(request.approvalCount > (approversCount / 2));
        request.vendorAccount.transfer(request.value);
        request.complete = true;
    }
}


```
## CommitteeCreator.sol
```solidity=

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;
import "./CAC.sol";

contract CommitteeCreator {
    CAC[] public deployedCommittee;

    function createCommittee(uint256 minimum) public {
        CAC c = new CAC(minimum, msg.sender);
        deployedCommittee.push(c);
    }
    function getDeployedCommittee() public view returns(CAC[] memory){
        return deployedCommittee;
    }
}



```

![](https://i.imgur.com/dO4RSpF.png)


![](https://i.imgur.com/Wyq4HZU.png)

![](https://i.imgur.com/edWHm2c.png)


![](https://i.imgur.com/pXdyoea.png)


![](https://i.imgur.com/y32WvPw.png)


# `1_initial_creator.js`
```javascript!

const cc = artifacts.require("CommitteeCreator")


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

## 在truffle>
```
deploy --reset
let cc = await CommitteeCreator.deployed()
cc.address
cc
```
## 更新的CAC.test.js
```javascript
const assert = require("chai").assert;
const CAC = artifacts.require("CAC.sol");
let cac
const VM_ERROR_STRING = "VM Exception while processing transaction:"

contract("test CAC", (accounts) => {
    beforeEach(async () => {
        //cac = await CAC.deployed();
        cac = await CAC.new(500, accounts[0]);
    })
    it("contract exist", async () => {
        assert(cac != null, "array should not be null")
        //console.log("cac address=", cac.address)
    })
    it("get minimum fund", async () => {
        const minimumFund = await cac.minimumFund();
        const v = minimumFund.toNumber();
        //console.log("type is", typeof v);
        // strict equal ===
        // equal ==
        assert.strictEqual(v, 500, "minimum fund should be 500");
    })
    it("get manager", async () => {
        const mgr = await cac.manager();
        console.log("mgr", typeof mgr);
        assert.strictEqual(mgr, accounts[0], "manager should be first account");
    })
    it("join, make request, and approve", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
    })
    it("join, make request, and approve twice", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.join({ from: accounts[1], value: 550 });
        await cac.join({ from: accounts[2], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        try {
            await cac.approvalRequest(0, { from: accounts[0] });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
    it("not enough fee", async () => {
        try {
            await cac.join({ from: accounts[0], value: 450 });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }
    })
    it("not approvers", async () => {
        await cac.createRequest("clean floor", 1000, accounts[9]);
        try {
            await cac.approvalRequest(0, { from: accounts[5] });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
})
```

## 更新過的CAC2.test.js
```javascript!
const assert = require("chai").assert;
const CAC = artifacts.require("CAC.sol");
let cac
const VM_ERROR_STRING = "VM Exception while processing transaction:"

contract("test more CAC", (accounts) => {
    beforeEach(async () => {
        //cac = await CAC.deployed();
        cac = await CAC.new(500,accounts[0]);
    })
    it("付款失敗", async () => {
        await cac.join({ from: accounts[0], value: 1000 });
        await cac.join({ from: accounts[1], value: 1000 });
        await cac.join({ from: accounts[2], value: 1000 });
        await cac.createRequest("clean floor", 888, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        try {
            await cac.executeRequest(0);
            assert(false);
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
    it("取得帳戶餘額", async () => {
        const amount1 = await web3.eth.getBalance(accounts[0]);
        console.log("餘額是", typeof amount1, amount1);
        const value = BigInt(amount1);
        console.log("value=", typeof value, value);
        console.log("轉成bigint可以作加減", value + 100n);
        console.log("轉成bigint可以作加減", value - 100n);
    })
    it("付款成功", async () => {
        await cac.join({ from: accounts[0], value: 1000 });
        await cac.join({ from: accounts[1], value: 1000 });
        await cac.join({ from: accounts[2], value: 1000 });
        await cac.createRequest("clean floor", 888, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        await cac.approvalRequest(0, { from: accounts[1] });
        const origBalance = await web3.eth.getBalance(accounts[9]);
        console.log("原本accounts[9]的餘額是", origBalance);
        await cac.executeRequest(0);
        const newBalance = await web3.eth.getBalance(accounts[9]);
        console.log("新accounts[9]的餘額是", newBalance);
        const remaining = BigInt(newBalance) - BigInt(origBalance);
        console.log("值是:", remaining);
        assert.strictEqual(BigInt(888), remaining, `值應該是${remaining}`);

    })
})
```

## `CC.test.js`
```javascript!
const CommitteeCreator = artifacts.require("CommitteeCreator.sol");
const CAC = artifacts.require("CAC.sol");
const assert = require("chai").assert;
require('chai').use(require("chai-as-promised")).should();
let cc;
beforeEach(async () => {
    cc = await CommitteeCreator.new();
    console.log("cc部署完成")
})
contract("Committee Creator測試", accounts => {
    it("用第一個帳號創建應該是第一個帳號作管理者", async () => {
        await cc.createCommittee(500);
        const cac1Addr = await cc.deployedCommittee(0);
        console.log(`cac的實例會在${cac1Addr}`)
        const allArray = await cc.getDeployedCommittee();
        console.log(`array在${allArray}`)
        const cac1 = await CAC.at(cac1Addr)
        const manager = await cac1.manager();
        assert.strictEqual(manager, accounts[0], "管理應該是第一個帳號")
    })
    it("用第二個帳號創建應該是第二個帳號作管理者", async () => {
        await cc.createCommittee(500, { from: accounts[1] });
        const cac1Addr = await cc.deployedCommittee(0);
        const cac = await CAC.at(cac1Addr)
        const manager = await cac.manager();
        assert.strictEqual(manager, accounts[1], "管理應該是第個二帳號")

    })
})
```
## CC2.test.js
```javascript!
const assert = require("chai").assert;
const CAC = artifacts.require("CAC.sol");
const CommitteeCreator = artifacts.require("CommitteeCreator.sol");
let cac
let cc
const VM_ERROR_STRING = "VM Exception while processing transaction:"
beforeEach(async () => {
    cc = await CommitteeCreator.new();
    console.log("cc部署完成")
})
contract("test CAC", (accounts) => {
    beforeEach(async () => {
        //cac = await CAC.new(500, accounts[0]);
        await cc.createCommittee(500, { from: accounts[0] })
        const cac1Addr = await cc.deployedCommittee(0);
        cac = await CAC.at(cac1Addr);
    })
    it("contract exist", async () => {
        assert(cac != null, "array should not be null")
        //console.log("cac address=", cac.address)
    })
    it("get minimum fund", async () => {
        const minimumFund = await cac.minimumFund();
        const v = minimumFund.toNumber();
        //console.log("type is", typeof v);
        // strict equal ===
        // equal ==
        assert.strictEqual(v, 500, "minimum fund should be 500");
    })
    it("get manager", async () => {
        const mgr = await cac.manager();
        console.log("mgr", typeof mgr);
        assert.strictEqual(mgr, accounts[0], "manager should be first account");
    })
    it("join, make request, and approve", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
    })
    it("join, make request, and approve twice", async () => {
        await cac.join({ from: accounts[0], value: 550 });
        await cac.join({ from: accounts[1], value: 550 });
        await cac.join({ from: accounts[2], value: 550 });
        await cac.createRequest("clean floor", 1000, accounts[9]);
        await cac.approvalRequest(0, { from: accounts[0] });
        try {
            await cac.approvalRequest(0, { from: accounts[0] });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
    it("not enough fee", async () => {
        try {
            await cac.join({ from: accounts[0], value: 450 });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }
    })
    it("not approvers", async () => {
        await cac.createRequest("clean floor", 1000, accounts[9]);
        try {
            await cac.approvalRequest(0, { from: accounts[5] });
            assert(false)
        } catch (e) {
            assert.isAbove(e.message.search(VM_ERROR_STRING), -1, "VM exception should happen")
        }

    })
})
```

## 使用
```
truffle develop
deploy --reset
 let cc =await CommitteeCreator.deployed()
 cc.createCommittee(500)
 let cacAddr1 = await cc.deployedCommittee(0)
 let inst1 = await CAC.at(cacAddr1)
 inst1.manager()
 accounts[0]
 inst1.minimumFund()
 (await inst1.minimumFund()).toNumber()
```

# 所有的程式碼
1. vs code:
    * https://drive.google.com/file/d/1gwoYAXI_kmCr1zknd4LtlzXRD-d3JvSd/view?usp=sharing
1. remix code:
    * https://drive.google.com/file/d/1UAgEi_MI_OX8I3TzXsiOzGUoSbyI4Jpw/view?usp=sharing 