---
# System prepended metadata

title: Smart Contrct

---

# 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:
![](https://i.imgur.com/bJOVTGm.png)

**Step 2** Input the deploy information under the JavaScript Environment:
![](https://i.imgur.com/Z7Idxtj.png)

**Step 3** If transaction is sucessfully, you can see the detial information of transaction.
![](https://i.imgur.com/oVPFArM.png)

##Use Truffle & Ganache run your contract
Step for install:
Download:
Git and Node.js
```
    npm install -g ganache-cli
    ganache-cli
```
![](https://i.imgur.com/qdj3Cjo.png)
ganache-cli 畫面
它會列出10 ELH錢包給你用作測試用
我們之後會選取第(0) 0xeFCeC35C6FDBDC1987296669377b6d16E79f16D2 (100 ETH)為owner
之後在YZTT.sol 檔案設定
address owner = 0xeFCeC35C6FDBDC1987296669377b6d16E79f16D2;
![](https://i.imgur.com/CEdOWpG.png)


安裝trufflesuite
```
    npm install -g truffle
    truffle --version //用作檢查是否安裝成功
```
安裝成功會顯示:
![](https://i.imgur.com/scGA8VO.png)
* 測試contract
* 編譯所寫的合約
```
    truffle compile 
```
之後部署合約
```
    truffle migrate (--reset)
```
結果如下:
![](https://i.imgur.com/542Gsa7.png)


## 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畫面:
![](https://i.imgur.com/WuDZrNm.png)
之後修正錯誤後成功的畫面:

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