Web3 基礎知識 - Sodility 教學(2) - 透過小專案學習 (募資專案)
學習目標
透過一個簡單的專案程式碼,來學習 sodility ,這邊會先貼出整份程式碼,底下會個別解釋 sodility 的程式語言知識
專案募資合約
簡介情境
- 有一個專案發起人,他發起一個募資專案,需要一筆目標金額
- 大家可以投資這個專案 (類似共同存錢到一個戶頭)
- 只有當募資成功(達到目標金額)時,這筆錢才會真正轉給專案發起人
- 如果募資失敗,投資的錢要能退還給各個投資人
1 | // SPDX-License-Identifier: MIT |
在 remix 上面編譯的時候,我這邊改 EVM VERSION 為 shanghai
之後部署的時候,我改 evm version 為: cancun
部署要記得設定募資的期望金額,也就是下圖的內容

部署完成之後,就可以如下圖跟合約互動

sodility 基本知識
變數
array
範例
陣列(array) 就是可以存放一組同類型資料的清單
1 | address payable[] listWallets; |
- 這個 array 要存錢包地址,所以 data type 是 address
- payable:讓地址可以 接收 Ether。
- 如果沒有 payable,你不能往這些地址發送 Ether。
[]:代表這是一個陣列,可以存放多個項目。
未來要放資料可以用 push
example 如下
1 | address payable[] listWallets; |
- 上述假設 wallet 是一個變數,且 data type 是 address
address
前面提過三個
- uint
- bool
- string
這邊講另一個
address → 專門存放錢包地址的資料型別
舉例如下
1 | address owner = msg.sender ; |
- msg.sender 是 sodility 內建的全域變數,全域變數常見的我放在最底下
建構子(constructor)
建構子(constructor)
- Constructor 是 Solidity 裡一種特殊的函數
- 合約被部署(deploy)時自動執行一次
- 功能:初始化
底下為範例
1 |
|
- public: 在合約內外都能被呼叫
- payable: 讓這個函數可以 接收與處理 Ether,這樣我們就能在部署合約時同時存入 Ether
modifier(修改器)
Solidity 中,modifier 是一種「附加條件」,可以套用在函數上,用來增加額外的邏輯控制。
常見用途:
- 限制誰可以呼叫(例如只有合約擁有者能執行)
- 檢查某些條件是否成立(例如判斷人是否已過世,才分配遺產)
底下範例
1 | Contract Test { |
上述是限制只有這個合約的擁有者,才能呼叫這個合約
require(msg.sender == owner):檢查呼叫合約的人(msg.sender)是否等於合約設定的擁有者(owner)_:代表「繼續執行函數本身的內容」。如果 require 條件不成立,函數會直接失敗,不會繼續往下執行。
modifier 就是控制函數的行為:
- 只能某帳號執行某函數
- 執行函數前要檢查什麼條件
- 函數執行結束後,要額外處理
資料結構
mapping (映射)
Solidity 裡,mapping 就像是一個「鍵值對(key-value store)」
- Key(鍵)→ 唯一識別的東西
- Value(值)→ 和該 key 對應的資料
底下範例
1 | mapping(address => uint) testing; |
- address → key
- uint → value
- testing 是這個 mapping 的名稱
sodility 全域變數
內建在 sodility 可以用的全域變數
msg (訊息相關)
| 變數 | 型別 | 說明 |
|---|---|---|
msg.sender |
address |
呼叫此函數的帳戶或合約地址 |
msg.value |
uint |
呼叫時隨交易傳入的 Ether 數量(單位 Wei) |
msg.data |
bytes |
呼叫函數的完整 calldata(原始輸入資料) |
msg.sig |
bytes4 |
calldata 的前 4 bytes(函數選擇器,用來識別呼叫哪個函數) |
tx (交易相關)
| 變數 | 型別 | 說明 |
|---|---|---|
tx.origin |
address |
發起這筆交易的 原始帳號(不管中間經過多少合約呼叫,永遠是最初發送交易的人的帳號) |
block 相關
| 變數 | 型別 | 說明 |
|---|---|---|
block.number |
uint |
當前區塊高度 |
block.timestamp |
uint |
當前區塊的 Unix 時間戳(秒) |
block.difficulty |
uint |
當前區塊的難度(PoW) |
block.gaslimit |
uint |
當前區塊允許的最大 Gas 限額 |
block.coinbase |
address payable |
當前區塊的礦工/驗證者地址 |
其他
| 變數 | 型別 | 說明 |
|---|---|---|
gasleft() |
uint256 |
目前剩餘的 Gas 數量 |
address(this).balance |
uint256 |
目前合約自身的 Ether 餘額 |
now |
uint |
⚠️ 舊版本的 block.timestamp(新版建議直接用 block.timestamp) |
相關整理
- 合約互動:常用
msg.sender(呼叫者) &msg.value(交易金額) - 安全性:避免用
tx.origin當作身份驗證。 - 時間/區塊控制:常用
block.timestamp(時間)、block.number(區塊高度)。 - Gas:
gasleft()可用於檢查是否還有足夠 Gas。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
