# Development

### Preparation

1. Install truffle

   ```
   npm install -g truffle
   ```
2. Install dependencies

   ```
   npm install
   ```
3. Install `ioctl` - the command-line tool to interact with IoTeX blockchain

install ioctl following the instructions: <https://docs.iotex.io/developer/ioctl/install.html>

### Compile contracts

`npm run build:contract`

### Deploy contracts

* **CycloneToken**

1. Deploy a CycloneToken `ct`

```
ioctl contract deploy bytecode CYCLONETOKEN_BYTECODE ABI_PATH '{"_operator": "OPERATOR_ADDRESS", "_lp": "INITIAL_LP_ADDRESS"}'
```

* **Timelock & GovernorAlpha**

1. Deploy Timelock `tl`

```
ioctl contract deploy bytecode TIMELOCK_BYTECODE TIMELOCK_ABI_PATH '{"admin_": DEPLOY_ADMIN_ADDRESS, "delay_": DELAY_IN_SEC}'
```

&#x20;   2\. Deploy GorvernorAlpha `ga` (e.g., voting duration:3 days)

```
ioctl contract deploy bytecode GORVERNOR_BYTECODE GOVERNOR_ABI_PATH '{"timelock_": TIMELOCK_ADDRESS, "sushi_": CYCTOKEN_ADDRESS, "guardian_": ADMIN_ADDRESS, "votingDuration_": 51840}'
```

&#x20;  3\. Set Timelock's pending admin to GovernorAlpha `ga`

```
 ioctl contract invoke function TIMELOCK_ADDRESS TIMELOCK_ABI_PATH "setPendingAdmin" --with-arguments '{"pendingAdmin_": GOVERNOR_ADDRESS}'
```

&#x20;  4\. Accept Admin from GovernorAlpha `ga` triggered by guardian&#x20;

```
 ioctl contract invoke function GOVERNOR_ADDRESS GOVERNOR_ABI_PATH "__acceptAdmin"
```

* **Aeolus**

1. Add Liquidity for CYC/IOTX on MimoFactory and receive CYC-IOTX LP Token
2. Deploy an Aeolus `as` with `ct` address

```
ioctl contract deploy bytecode AEOLUS_BYTECODE ABI_PATH '{"_cycToken": CYC_TOKEN, "_lpToken" : LP_TOKEN}'
```

&#x20;   3\. Invoke `ct`.addMinter() to set `as` to be minters for CYC token

```
ioctl contract invoke function CYCTOKEN_ADDRESS CYCTOKEN_ABI_PATH "addMinter" --with-arguments '{"_minter": AEOLUS_ADDRESS}'
```

* **CoinCyclone, ERC20Cyclone**

1. Deploy Hasher `hr`

   ```
   ioctl contract deploy bytecode HASHER_BYTECODE
   ```
2. Deploy Verifier `vr`

   ```
   ioctl contract deploy bytecode VERIFIER_BYTECODE
   ```
3. Deploy CoinCyclone `cc`, ERC20Cyclone `ec` linked by Hasher `hr` with `as`, `vr`, `ct`, `mf`and if necessary, XRC20 token address

   ```
   link CoinCyclone_BYTECODE/ERC20Cyclone_BYTECODE with HASHER_ADDRESS (use linker.js)
   ```

   ```
   ioctl contract deploy bytecode CoinCyclone_LINKED_BYTECODE CoinCyclone_ABI_PATH'{"_verifier": VERIFIER_ADDRESS, "_cyctoken": CYCTOKEN_ADDRESS, "_mimoFactory": MIMOFACTORY_ADDRESS, "_aeolus": AEOLUS_ADDRESS, "_initDenomination" : DENOMINATION_AMOUNT, "_denominationRound": DENOMINATION_ROUND, "_merkleTreeHeight" : MERKLETREE_HEIGHT, "_operator": TIMELOCK_ADDRESS}'
   ```

   ```
   ioctl contract deploy bytecode ERC20Cyclone_LINKED_BYTECODE ERC20Cyclone_ABI_PATH '{"_verifier": VERIFIER_ADDRESS, "_cyctoken": CYCTOKEN_ADDRESS, "_mimoFactory": MIMOFACTORY_ADDRESS, "_aeolus": AEOLUS_ADDRESS, "_initDenomination" : DENOMINATION_AMOUNT, "_denominationRound": DENOMINATION_ROUND, "_merkleTreeHeight" : MERKLETREE_HEIGHT, "_operator": TIMELOCK_ADDRESS, "_xrc20Token" : XRC20TOKEN_ADDRESS}'
   ```
4. Invoke `ct.addMinter()` to set `cc` and `ec` to be minters for CYC token

   ```
   ioctl contract invoke function CYCTOKEN_ADDRESS CYCTOKEN_ABI_PATH "addMinter" --with-arguments '{"_minter": CoinCyclone_ADDRESS}'
   ioctl contract invoke function CYCTOKEN_ADDRESS CYCTOKEN_ABI_PATH "addMinter" --with-arguments '{"_minter": ERC20Cyclone_ADDRESS}'  
   ```
5. Invoke `as`.addAddressToWhitelist() to set `cc` and `ec` to be whitelists for Aeolus to invoke `addReward()`&#x20;

   ```
   ioctl contract invoke function AEOLUS_ADDRESS AEOLUS_ABI_PATH "addAddressToWhitelist" --with-arguments '{"addr": CoinCyclone_ADDRESS}'
   ioctl contract invoke function AEOLUS_ADDRESS AEOLUS_ABI_PATH "addAddressToWhitelist" --with-arguments '{"addr": ERC20Cyclone_ADDRESS}'
   ```

### Test contracts

1. node version `nvm use 11.15.0`
2. build zk circuits `npm run build`
3. if you want to use `test` network, just run `npm run test` (default).

   If you want to use `development` network,

   * modify truffle-config.js (uncomment development network)
   * run `ganache-cli i 1337`
   * run `npm run test`

### Interaction with Cyclone contracts \[Anonymity Mining]

1. Requirements
2. `nvm use 11.15.0`
3. `npm install -g npx`
4. Set up .env file
   * `cp .env.example .env`
   * `vi .env` - add your private key, deployed contract address and denomination value
5. Build zk circuits: `npm run build`. Note that if you want to build zk circuits (including verifier.sol, proof/verify-keys) locally, you need to:
   * `npm uninstall websnark`
   * `npm install websnark@"git+https://github.com/tornadocash/websnark.git#2041cfa5fa0b71cd5cca9022a4eeea4afe28c9f7"`
   * `npm run build:local` - It might take more than 10 minutes as it performs the trust-setup locally.
6. Deposit
   * Testnet

     `./client.js deposit IOTX|XRC20 --rpc http://api.testnet.iotex.one:80`
   * Mainnet

     `./client.js deposit IOTX|XRC20 --rpc http://api.iotex.one:80`
7. Withdraw
   * Testnet

     `./client.js withdraw NOTE RECIPIENT_ADDRESS --rpc http://api.testnet.iotex.one:80 --relayer RELAYER_URL`
   * Mainnet

     `./client.js withdraw NOTE RECIPIENT_ADDRESS --rpc http://api.iotex.one:80 --relayer RELAYER_URL`

### Interaction with Aeolus contract \[Liquidity Mining]

1. Add Liquidity for CYC/IOTX on MimoFactory and receive CYC-IOTX LP Token
2. Deposit&#x20;

* Approve CYC-IOTX LP Token

```
ioctl xrc20 approve AEOLUS_ADDRESS AMOUNT -c LPTOKEN_ADDRESS
```

* Deposit CYC-IOTX LP Token

```
ioctl contract invoke function AEOLUS_ADDRESS abi/Aeolus.json "deposit" --with-arguments '{"_amount": AMOUNT}'
```

&#x20;  3\. Withdraw&#x20;

```
ioctl contract invoke function AEOLUS_ADDRESS abi/Aeolus.json "withdraw" --with-arguments '{"_amount": AMOUNT}'
```

### Interaction with GovernorAlpha contract \[Governance]

1. Self-delegate or delegate your CYC token for governance. If you do not delegate your votes, the token will not be considered as voting power.&#x20;

```
ioctl contract invoke function CYCTOKEN_ADDRESS abi/CycloneToken.json "delegate" --with-arguments '{"delegatee": ADDRESS_YOU_WANT_TO_DELEGATE}' -s mainnet -y
```

&#x20;   2\. Propose a new change in cyclone contracts such as updateConfig, changeGovDAO, and updateVerifier. The proposer should have more than 1000 CYC Token. Voting will run for 3 days. -- Use [abi-encoder](https://adibas03.github.io/online-ethereum-abi-encoder-decoder/#/encode) to get encoded argument data.

```
ioctl contract invoke function GOVERNOR_ADDRESS abi/GovernorAlpha.json "propose" --with-arguments '{"targets": [CYCLONE_ADDRESS], "values": [0], "signatures": ["updateConfig(uint256,uint256,uint256,uint256)"], "calldatas": ["..."], "description": "update configs in cyclone contract"}'
```

&#x20;   3\. During the 3 days of voting duration, token holders who self-delegate or delegate can cast votes for a certain proposal.

```
ioctl contract invoke function GOVERNOR_ADDRESS abi/GovernorAlpha.json "castVote" --with-arguments '{"proposalId": 1, "support": true}'
```

&#x20;  4\. After 3 days of voting duration, if the proposal gets more than 4000 CYC votes, the proposer can queue the transaction into Timelock.

```
ioctl contract invoke function GOVERNOR_ADDRESS abi/GovernorAlpha.json "queue" --with-arguments '{"proposalId": 1}'
```

&#x20;  5\. After the timelock delay, the proposer can execute the transaction in timelock.

```
ioctl contract invoke function GOVERNOR_ADDRESS abi/GovernorAlpha.json "execute" --with-arguments '{"proposalId": 1}'
```

###
