---
# System prepended metadata

title: Smart Contract-1 基礎篇範例
tags: [Smart Contract]

---

###### tags: `Smart Contract`

# Smart Contract-1 基礎篇範例
已看過一遍solidity文件 開發了一些發NFT和小遊戲的合約
但想多了解一下別人在開發些什麼
偶然找到這個網站 
https://solidity-by-example.org/
看來從基礎的變數介紹到swap和一些application都有
因此做一個閱讀日記 順邊溫習一下solidity
此篇是基礎篇 大部分都是語法

# 第一篇基礎語法範例
* Hello World 

code基礎Hello World

* First App 

一個簡易計數器 count+-
* Primitive Data Types

變數型別
1. boolean 01
2. uint 無符號 0~2^256
3. int 有符號 -2^256~2^255
4. address 40位的十六進位
補充:私鑰是64位的十六進位
透過ECSDA產生66位的公鑰 擷取後面的40位  即是以太坊的地址

* Variables

變數區域 local global 區域是不是存於blockchain

* Constants

變數設定 寫下後只能在編譯時賦值 不能用互動區塊鏈資料的code msg.sender等給予

* Immutable

變數設定 跟Constants很類似 差在Immutable可以透過constructor給值

* Reading and Writing to a State Variable

簡單透過function賦值

* Ether and Wei

Gas的基本單位Wei  1ether=10^18wei(1e18) 

* Gas and Gas Price

gas spent * gas price amount of ethe
gas spent是你花了多少gas
gas price價格是浮動的 取決於當前壅塞狀況

gas limit 付出gas的極限 可由合約設定
gas block limit 是由鏈決定的

* If / Else

if else邏輯

* For and While Loop

無限迴圈 會寫題應該不陌生 但不建議使用 邏輯錯誤直接跑到gas limit

* Mapping

常用到Mapping(key,value) 也可以塞自己設定好的struct 支援delete

* Array

陣列大家不陌生 支援 push pop length remove(動態改變的)
* Enum

序列 其實和mapping挺像 比較方便的語法

* Structs

由自己設定的結構 要賦值需用storage 宣告出來才可以
若是單純呼叫要取值就不用 

* Data Locations - Storage, Memory and Calldata

Storage 儲存在區塊鏈的變數
Memory 當地變數 function跑完就消失
Calldata 原理也是 但是只能在參數區域宣告 且無法被覆蓋修改 
我的判斷偏向邏輯使用

* Function

函式 solidity允許複數的return (uint,address,bool)

* View and Pure Functions

view 沒有區塊資料會被修改 但可以讀取區塊資料 當使用者要return一些狀態通常都是view
Pure 沒有區塊資料會被修改 連讀取區塊資料都不行 純計算用

* Error

require 可以條件式的判斷 (if,"error") 會退Gas
revert  直接error ("error")
assert 可以條件式的判斷 (if,"error") 不會退Gas
通常用來判斷code邏輯是否出錯 適用於比較嚴重的BUG跟internal的函式

* Function Modifier

修飾符 是一種檢查用的function 可在function開始前或結束執行
乎叫在定義其他function變數的位置
EX:常見的 onlyOwnoer 
Modifier的特殊用法 _; 定義Modifier的code在開始前後執行
locker開始前true 結束後false
  
    modifier noReentrancy() {
        require(!locked, "No reentrancy");

        locked = true;
        _;
        locked = false;
    }

* Events

用來記錄那些事件發生
宣告 event a(address,uint)
執行 emit a(address,uint)

* Constructor

合約宣告時會執行
可以用來初始化些資料跟傳入資料

* Inheritance

java的繼承蓋念
contract A is B
需要被實踐的用virtual
要覆蓋就override

內容有一個有趣的範例
contract B,contract C 都override foo()
在contract E is B,C 中 執行 foo override(){super.foo}
會執行C 因為C是最右邊的父親 也是最後繼承的

* Shadowing Inherited State Variables
繼承的變數不能透過function修改
若要更改繼承的變數 需在constructor 重新定義該變數 繼承的變數就會被改變了

* Calling Parent Contracts

contract A is B
可以用super.foo() or B.foo()呼叫

* Visibility

定義function的變數
public 能公開使用也可繼承
private 不可繼承 只能在合約內使用
internal 可繼承 只能在合約內使用
external 不可繼承但可以公開使用

* Interface

介面 基本是用來繼承override的 
ERC721I就是 基本上是宣告一個介面 必須是external
不能有constructor跟State變數

繼承的合約拿來override覆蓋並實現 我的想法是為了可讀性而做的

* Payable

function 地址的變數 若有發送eth都需要新增

* Sending Ether - Transfer, Send, and Call
三種發送token的方法 推薦用call 具有重入保護的特質
* Fallback
退回的function
發生在一些錯誤情形  呼叫不存在的函式
或是接受以太但其沒有receive()
* Call
底層的呼叫方式 可以透過某個地址直接呼叫他的function執行
更改的是被call合約的區塊鏈資料
foo()就是 _addr本來就有的Function

_addr.call{value: msg.value, gas: 5000}(
            abi.encodeWithSignature("foo(string,uint256)", "call foo", 123)
        );

* Delegatecall
與call用法類似 如果A cotract在他的程式內執行 B.delegatecall
delegatecall會執行於A的storage裡面 call就是執行B的
假設AB都有一個 X=0 function功能是x+1
B.call B的X=1 A的X=0
B.delegatecall B的X=0 A的X=1

* Function Selector

當呼叫function時 前四個bytes是選擇的function
4 bytes= 32 bits 換算成十六進位 
是8位數的16進位 EX: 0xa9059cbb
範例提到是也許可以透過實作減少GAS

* Calling Other Contract

這是沒有繼承的狀況 呼叫其他合約的function
同理更改的是其他合約的storage資料 跟本身合約沒有關係
比較像操作別人的合約

可以用底層的call
也可以直接A.foo()


* Creating Contracts from a Contract

讓呼叫的合約 透過new contract的方式
範例是自己製造一個car合約跟factor car 其他人能透過factor去實現
https://solidity-by-example.org/new-contract/

* Try / Catch

寫js應該不會陌生
成功就執行try 失敗 catch
範例說只能執行在 external Calls跟合約new的時候
* Import

import "../xxx.sol"
也能只import function or var
import "varA,funcionC,structB" from "../xxx.sol"
也可以透過URL import! 這倒是第一次知道
* Library

有再寫code應該不會難懂 庫 通常都是被拿來取用的
在smart contract中 如果Library全部都是internal
程式碼就必須要鑲嵌在同一個專案裡

其他狀況 都必須先將library部署並連結 在要使用的contract部署前
* ABI Encode

ABT編碼 abi.encodepacked
abi.encodeWithSignature("transfer(address,uint256)", to, amount);

abi.encodeWithSelector(IERC20.transfer.selector, to, amount);
return abi.encodeCall(IERC20.transfer, (to, amount));
* ABI Decode

附上範例比較清楚

https://solidity-by-example.org/abi-decode/
encode 將數據加密byte
decode 將byte解密回數據
範例是將加密的data傳入 以及有哪些變數型態 
解密後傳回

* Hashing with Keccak256

加密hash的Keccak256 原理已寫過文 就不贅述
可以產生一段隨機的hash 64位的16進位數值

範例提到幾種用法
keccak256產生獨特的輸入
keccak256產生一段Compact加密簽名(透過簽名而不是一長串的輸入)

* Verifying Signature
簽名驗證的流程
原理很簡單
message=keccak256(abi.encodePacked(a,b,c,d))
乙太訪的要加上 "\x19Ethereum Signed Message:\n32"

ecrecover 會返回簽名者的公鑰
此處的signature他是用預設的
ecrecover(message,signature)

* Gas Optimizations
節約gas的技術 這倒是小實用
用calldata替換memory 
用memory load state var
++i代替i++
用暫存呼叫陣列的元素 這跟平常寫code邏輯一樣 省資源 
不用一直去原始的位置呼叫
https://solidity-by-example.org/gas-golf/

* Bitwise Operators
二位元的運算 有種回到數位邏輯的時光 算一算也5年前了吧 真感慨
and & 
只介紹一個  and同樣的會變成1 不同的變成0
1 1 1 0 
1 0 1 1
- - - -
1 0 1 0
or |
xor ^
shiftLeft <<
shiftRight >>
一些瑣碎的就不介紹 用到的機會不太大

資源: https://solidity-by-example.org/
