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