# Quorum 研究筆記(11/14)
## solidity入門
### ERC20(26)
官網定義:design and issue your own cryptocurrency
如果今天要創立一個幣,那我還要自己創一個區塊鏈,那就創一個以太坊,讓每個人都可以創自己的幣以及智能合約,可是每個人的幣如果標準都不同會無法相容,所以就制定ERC20標準,只要有用到以下方法,即稱符合ERC20:

只要方法裡面有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執行跳出,則該次交易所有的數值變動都會視為無效。

我們通常會把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;
}
```