###### 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/