---
# System prepended metadata

title: Quorum 研究筆記(11/14)

---

# Quorum 研究筆記(11/14)
## solidity入門
### ERC20(26)
官網定義：design and issue your own cryptocurrency
如果今天要創立一個幣，那我還要自己創一個區塊鏈，那就創一個以太坊，讓每個人都可以創自己的幣以及智能合約，可是每個人的幣如果標準都不同會無法相容，所以就制定ERC20標準，只要有用到以下方法，即稱符合ERC20：
![](https://i.imgur.com/cbZRgq5.jpg)
只要方法裡面有revert，當次交易會被拒絕掉
#### transfer原理
小名要轉給小黃5個代幣，並不是直接把幣轉給小黃，而是轉幣給智能合約，直接修改鏈上mapping的資料(要付gas)，幣都不是存在自己這邊，而是存在智能合約之中。
```
function approve(address spender, uint tokens) public returns (bool success){
allowed[msg.sender][spender] = tokens;
emit approval(msg.sender, spender, tokens);
return true;
}

function transferfrom(address from, address to, uint tokens) public returns(bool success){
balances[from] = balances[from] - sub(tokens);
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
emit transfer(from, to, tokens);
return true;
}
```
使用者同意DEX(Decentralized Exchange去中心化交易所)使用自己的5個代幣，dex就會轉移那5個代幣給自己。但系統不會檢查使用者是否真的有五個代幣，所以使用者可以預先批准dex使用自己還沒有的代幣。
### 異常exception(27)
如何限制可以呼叫我制定的方法的人？
```
address public owner = 0x.....

function fu_abc() public{
if(msg.sender == owner)
abc++;
} 
```
透過if的方法，我們就可以限制必須要是owner才可以存取該方法
```
function fu_abc() public{
require(owner == msg.sender, "使用者不對");//true or false
require(msg.value >= 10000);
abc++;
} 
```
如果require裡面的條件為false，則這個方法會跳出，整個交易會直接壞掉；且會印出後面的字串。

另外，還有以下的保護方式：
```
function ex1(uint x) public{
if(x < 100){
revert("x can't be smaller than 100!")
}
interger_1 = x;
}

function ex2(uint x) public{
interger_1 = x;
assert(integer_1 >= 100);//if the statement is false, then it'll fail
}
```
不管是revert、assert、require執行跳出，則該次交易所有的數值變動都會視為無效。

![](https://i.imgur.com/EFLhQ0P.jpg)
我們通常會把assert擺在最後面作為最後一層的檢查，如果發生錯誤了通常就會是最嚴重的問題才會發生。

## solidity 進階
### modifier(28)
```
//自己定義一個modifier
modifier onlyowner{
require(msg.sender == owner);

_;//底下function執行內容的簡寫

require(integer1 <= 100);//可以執行完內容之後再檢查一次
}

function myfunc(uint x) public onlyowner{
x++;
integer1 += x;
}
```
```
modifier onlyowner(uint y){
require(y > 30);
_;//
}

function myfunc(uint x) public onlyowner(x){
integer1 += x;
}
```
### (29?)
### 合約結構、哈希(30)
```
pragma solidity ^0.4.24 //大於0.4.24版本編譯即可
pragma solidity 0.4.24 //只能用0.4.24版本編譯
```
一個合約的基本樣子：
```
prama solidity ^0.4.24;

contract class30{
    address public owner;
    uint public integer;
    //全域變數
    
    constructor() public {
        owner = msg.sender;
        integer = 0;
    }
    
    modifier onlyowner {
        require(msg.sender != owner);
        _;
    }
    
    function add_check_sender(uint x)public onlyowner{
        integer += x;
    }
}
```
#### hash方法
- 改變一點輸入，輸出巨變
- 無法導回內容
- 不同輸入即不同結果
```
function keccok_256_2(string str1, string str2) public view returns(bytes32){
    return keccok256(abi.encodePacked(str1,str2,msg.value,now,...))
    //裡面可以裝很多東西
}
```
```
function pay() public payable{
}
//改變了coinbase的高度的值
//所以必須要pay完，底下的亂數產生器才能再產生一個不同的亂數
//因為亂數產生需要用到coinbase

//粗糙的亂數產生器
function rendom() public view returns(uint){
    bytes32 result = keccok256(block.coinbase, blockhash(block.number-1)));
    return uint(result) % 1000 / 1;
}
```
### library (31)
將一些共同需求的程式碼整理成大家都可以用的函式庫，加速每個人的開發進程。
例：照相app裡面有修圖library、錄影拍照library與qrcode library之類的。
```
pragma solidity ^0.4.24;

library safemath{
    
    function add(uint a, uint b){
    ...
    }
    
    function sub(uint256 a, uint256 b){
    ...
    }
}

pragma solidity ^0.4.24;

import"./safemath.sol"

contract class31{
    using safemath for uint;
    
    function use_add(uint a, uint b) public pure returns(uint){
        return a.add(b);
    }
    //the result equal a+b
    //a.add(b)的a會對應到library的add中uint的a
}
```
為甚麼我們需要再寫一個library來乘除數字？
因為我們可以在safemath裡面多一個溢位防護機制，可進而避免駭客攻擊、避免資安疑慮。
### address方法、餘額與自毀(32)
```
function myfunc() public{
    address myaddress = 0x...;
    //我們可以對這個myaddress做甚麼？
    //查詢餘額myaddress.balance
    //轉幣myaddress.transfer
    //轉幣myaddress.send
    
    function func1() public view returns(uint){
        return owner.balance;
    }//傳回使用者餘額
    
    function func2() public view returns(uint){
        return address(this).balance;
    }//傳回這份智能合約的餘額
}
```
#### 這部影片後面斷掉

### reference (33)
- 變數存在記憶體(memory)還是鏈上(storage)？存在記憶體上代表只用一次，但如果存在鏈上，因為每個節點都幫你存資料，所以需耗費的gas較貴。
- 預設全域型變數就是storage，區域型為memory
全域型變數都是存在鏈上：
```
prama solidity ^0.4.24;

contract class33{
    uint public abc = 0;
    mapping(address->uint) public balance;
    function use() public pure returns(uint){
        return 5;
    }
}
```
區域型變數代表存在memory，只有當次有效：
```
prama solidity ^0.4.24;

contract class33{
    uint public abc = 0;
    function use() public pure returns(uint){
        uint ggg = 5;
        return ggg;
    }
}
```
storage與memory為保留字：
```
struct fruit{
    uint id;
    string name;
}

fruit[12] public fruitarray;

mapping(address => fruit) public fruitmapping;

function ex1(uint i, string n)public{
    fruit storage fruit1 = fruitarray[0];
    fruit1.id = i;
    fruit1.name = n;
    
    fruit storage fruit2 = fruitmapping[0x...];
    fruit2.name = n;
}

function ex2(uint i, string n)public view{
    //不會改變鏈上資訊
    fruit memory fruit1 = fruitarray[0];
    fruit1.id = i;
    fruit1.name = n;
}
```