# Smart Contrct
Develop: https://remix.ethereum.org/
4/29
智能合約介紹
智能合約不只用在轉帳上面,還可以用在不同的客制化上。
智能合約是可以跑的程式碼,減少對中介者的需求
智能合約具有以下屬性:
address
Ether balance
state and methods
智能合約的程式類似物件導向中的 class and object relationship
# Solidity Language
程式語言介紹
這次所使用的語言是Solidity
## Contract Structure
1. **Pragma**
define the Solidity version (E.G: pragma solidity ^0.8.0;)
2. **Import**
Use another contract component or funtion, which likes javaScript's require or Python's import
If you want to use another contract instance define, you need to define the contract address
(E.G: import "./IERC20.sol";)
3. **Contract/Interface/Library**
Language look likes javaScript
It is like class, not void main()
## Data Type
* **Value type**: uint/int, string, bool, address
Address: can be 外部擁有地址(EOA) or 合約地址 Contract Address
* **Reference** type(self:which is control the memory): struct, array, mapping
Array: save with same type array
Struct: hybird data type
Enum: Not always use
Mapping: Key-value
## Operators
normal: -+*/%
## Control Structures
if-else, for, while
## Function And Returms
function name() public view returns (string memory) {
return _name;
}
view => const, I can not change it
returns (string memory) //Which instance return
## Rejecting Functions
Assert => 不推薦使用
Require => 某特定條件會拒絕交易,在區塊鍵上拒絕,而if-else是logic reject(self:意味區塊鍵會接受)
Revert
## Events
唯一可以與外界溝通的資料結構,跟全世界說今天我要轉帳出去,全世界都知道這事件發生
如何要跟交易所要資料,都要通過Event來做‧
## Global Variable
每一筆交易都會有一個發起人
msg是載明交易的一些資訊
* msg.sender: sender address
* msg.balance: sender LTE amount
* msg.value: this transfer amount
* msg.data: this transfer data
## Code
```
contract Your_Contract_Name{
uint _totalSupply; 0以上的一個數字 token的發行
uint _decimal; 小數點 is like 100 * 10^-6
string _name = "Input_Name"; token name
string _symbol = "Symbol_Name"; 這是一個代號 token symbol
address owner = owner_address(你的錢包address)
struct TransferLog {
address _sender;
address _receiver;
uint _amount; //Transcation amount
uint _time;
_balance[msg.sender] = totalSupply_;//建立這合約的人先充值進去
}
/*The log which people I transfered before*/
Transferlog[] transferlog;
/*Balance is save the token amount*/
mapping (address => uint) _balances; 這一個Mapping 是說每一個address對上一個uint
/* 定義Transfer事件*/
event Transfer(address indexed _sender, address indexed _receiver, uint _amount);
/*constructor for your smart contract*/
constructor (string memory name_, string memory symbol_, uint totalSupply_, uint decimal_) public{
_name = name_;
_symbol = symbol_;
_totalSupply = totalSupply_;
_decimal = decimal_
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function balanceOf(address addr) public view returns (uint) {
return _balance[addr];
}
/* 轉帳 */
/** 從A轉到B
* A的餘額要足夠
* 轉帳記錄要丟進去transferLog裡面
* 發送Transfer事件
*/
function transfer(address _receiver, uint _amount) public {
address _sender = msg.sender;
/* cretical section */
require (_balance[_sender] >= _amount, "Insufficient Amount of sender"); //Check sender wallet whether Enough
_balance[_sender] = _balance[_sender] - _amount;
_balance[_receiver] = _balance[_receiver] + _amount;
/* Transfer事件發送 */
emit Transfer(_sender, _receiver, _amount);
/* TransferLog */
TransferLog memory log = TransferLog({
_sender: _sender,
_receiver: _receiver,
_amount: _amount,
_time: block.timestamp
});
transferLog.push(log); // Record this transfer
}
}
```
開發概念解析
Provider: 可以想成是一個node,他可以幫你與區塊鏈進行溝通
5/03
Truffle:
It is develop Environmet, which is use for testing ETH framework and deploy
Ganache:
用於開發的人個人區塊鏈,可以用作測試,部署你的contract
會提供Virtual User
# Contract Test in Remix
**Step 1** Compile your contract:

**Step 2** Input the deploy information under the JavaScript Environment:

**Step 3** If transaction is sucessfully, you can see the detial information of transaction.

##Use Truffle & Ganache run your contract
Step for install:
Download:
Git and Node.js
```
npm install -g ganache-cli
ganache-cli
```

ganache-cli 畫面
它會列出10 ELH錢包給你用作測試用
我們之後會選取第(0) 0xeFCeC35C6FDBDC1987296669377b6d16E79f16D2 (100 ETH)為owner
之後在YZTT.sol 檔案設定
address owner = 0xeFCeC35C6FDBDC1987296669377b6d16E79f16D2;

安裝trufflesuite
```
npm install -g truffle
truffle --version //用作檢查是否安裝成功
```
安裝成功會顯示:

* 測試contract
* 編譯所寫的合約
```
truffle compile
```
之後部署合約
```
truffle migrate (--reset)
```
結果如下:

## Truffle test
### migrations File
在migrationso內建立161892708_yzt.js
```
const YZT = artifacts.require("YZT")
module.exports = function(deployer) {
// Use deployer to state migration tasks.
deployer.deploy(YZT,
"YuenZe Token",
"YZT",
6,
10000000000,
)
};
```
### testFile write
建立一個test/yzt.js file用作測試contract
Code:
```
const YZT = artifacts.require("YZTT");
/*
* uncomment accounts to access the test accounts made available by the
* Ethereum client
* See docs: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript
*/
contract("YZTT", function (accounts) {
let yztContract;
before("Deploy YZT contract", async () => {
console.log("deploying YZT contract...")
yztContract = await YZT.deployed()
//The test data in migrations
assert.equal(await yztContract.owner(), accounts[0], "wrong contract owner"); //confirm the accounts is my supply amount
assert.equal(await yztContract.name(), "YuenZe Token", "wrong contract name");//Test the name
assert.equal(await yztContract.symbol(), "YZTT", "wrong contract symbol");//Test the symbol
})
//confirm transfer doesn't have problem
it("confirm transfter does not have problem", async () =>
{
//test logic
//test A transfer ot B
//Whether A correct reduce amount
//Whether B correct update amount
//A -> accounts[0]
//B -> accounts[1]
//1. take the contract instance
const yztContract = await YZT.deployed();
//2. run the contract, A transfer 1 dollers to B
await yztContract.transfer(
accounts[1], /* The receiver address*/
100,//represent 1 dollers, because decimal is 2
{
from: accounts[0] /* A send this transition */
}
)
//3. Check the balance A and B
const aBalance = yztContract.balanceOf(accounts[0]);
const bBalance = yztContract.balanceOf(accounts[1]);
assert.equal(aBalance, 9900, "A balance is error");
assert.equal(bBalance, 100, "B balance is error");
//4. Finish;
return true;
});
it("should have correct contract name", async function () {
return await yztContract.name(), "YuenZe Token", "wrong contract name";
});
});
```
上面的test logic:
Check owner, name, symbol
之後看contract跑完之後是否正確
test A transfer ot B
Whether A correct reduce amount
Whether B correct update amount
當中assert.equal(await yztContract.symbol(), "YZTT", "wrong contract symbol");
是指yztContract.owner() == accounts[0],如果不等於,就輸出"wrong contract symbol"
Error畫面:

之後修正錯誤後成功的畫面:
