親眼讀這門語言,而不只是聽說它
你已經聽說過:智慧合約就是*住在某個地址上的程式碼加狀態*。但到目前為止,這都只是從外部給出的描述。讓我們打開盒子、讀一讀真正的程式碼——因為編寫合約的主力語言 Solidity,遠沒有看上去那麼神秘。如果你曾填寫過一張帶命名欄位的表單,又按下過某個只做一件特定事情的按鈕,那麼你其實已經懂得它的輪廓了。
下面是一份完整、能跑的合約:一座小小的銀行,記著每個地址各自存了多少。它只有寥寥幾行,但 Solidity 裡每一個要緊的概念都已包含其中。先從頭到尾通讀一遍,然後我們再慢慢逐句走過它。
contract PiggyBank {
// STATE: a table from address -> balance
mapping(address => uint) public balances;
function deposit() public payable { // pay in; coins ride along
balances[msg.sender] += msg.value;
}
function withdraw(uint amount) public { // take back only yours
require(balances[msg.sender] >= amount, "too much");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}逐行走讀這份程式碼
`mapping(address => uint) public balances;` 這一行,就是這份合約的全部記憶。mapping(映射)是一張查找表:遞給它一個地址,它就還你一個數字。這張表*就是*鏈上狀態——它會永遠留存,而每一個節點都持有同一份副本。`public` 這個詞,只是表示任何人都可以讀取它,而這正是合約預設的性情:天生開放。
每一個 `function`(函式)都是世界可以觸發的一條規則。`deposit()` 被標記為 `payable`,意思是一次呼叫可以攜帶著錢幣而來;所發送的金額會以 `msg.value` 的形式出現,而 `msg.sender` 則是發起呼叫的那個地址。`balances[msg.sender] += msg.value;` 這一行讀取呼叫者當前的餘額,再寫回一個更大的值。關鍵在於,合約從不需要追問*你是誰?*——早在這個函式運行之前,網路就已經透過呼叫者的數位簽章證明了其身分。
`withdraw()` 展示了每一位 Solidity 讀者都必須學會的那個習慣:守衛(guard)。`require(balances[msg.sender] >= amount, "too much")` 這一行是一道檢查關卡。如果條件為假,整次呼叫便會被回滾(revert)——徹底撤銷,彷彿從未發生過,並把錯誤訊息交還回來。唯有檢查通過,餘額才會減少、錢幣才會發出。正是這條「全有或全無」的規則,護住了一個公開的、人人可呼叫的程式,使其不被掏空。
被封的盒子:合約無法向外張望
現在要說那個幾乎讓所有人都吃驚的邊界了。我們的存錢罐之所以能成立,是因為每一個節點在以太坊虛擬機裡運行它,都會得出*完全*相同的答案。這種確定性正是信任的源頭——但它是有代價的。合約被允許觸碰的,只有每個節點都能就之達成一致的東西:它自己的狀態、所發送的金額、呼叫者的地址。它被封在了鏈內。
於是,合約取不到一個網頁,讀不到今天的天氣,不知道黃金的價格,甚至說不出真實世界此刻是幾點。為什麼不能?設想它試圖呼叫一個天氣網站。一個節點也許拿到「22°C」,另一個晚了一秒拿到「23°C」,第三個則可能直接逾時。這下節點之間就對不上了,共識隨之崩碎,鏈也無從判定哪一段歷史才是真的。為了保住確定性,EVM 乾脆徹底禁絕了任何通往外界的窗口。
預言機:把世界搬上鏈的信使
可是,我們希望合約去做的事,有太多*取決於*外部世界。一份在航班延誤時賠付的保險合約,需要知道航班確實延誤了;一筆在抵押物貶值時清算的貸款,需要一個價格。區塊鏈預言機,就是把這類事實搬過那堵牆的橋。它不是什麼魔法之眼——它是一段運行在鏈外的軟體,先讀取真實世界,再把答案作為一筆普通交易寫進某份合約的狀態。事實一旦上了鏈,每個節點便都能看見它、就它達成一致。
REAL WORLD OFF-CHAIN ON-CHAIN
---------- --------- --------
flight delayed -> oracle reads -> writes "delayed = true"
ETH price $... -> the data, then -> into a price contract
match score -> sends a tx -> that dApps can read
the wall the EVM cannot see through: | <-- here
A contract only ever reads what an oracle
has ALREADY written into on-chain state.你或許聽說過的許許多多去中心化應用,正是靠這一套在運轉:借貸市場、預測市場、保險,以及一切繫於真實價格或真實事件之上的東西。合約保持簡單而確定,預言機則去幹那件伸手探入現實的髒活累活。兩者合在一起,才讓鏈上程式碼終於能夠*回應*鏈下的世界。
薄弱的一環:你信誰說的真相?
麻煩就在這裡,而且茲事體大。我們用整整這條線索,搭起了一個你無需信任任何人的系統——可預言機卻悄悄把「告訴合約什麼是真」的權力,交給了某一個單一來源。倘若那個來源出了錯,或被收買,它下方那份無懈可擊的程式碼,就會無懈可擊地在一個謊言之上執行。一份在航班延誤時賠付的合約,只要預言機*聲稱*航班延誤了,它就會照賠不誤。這就是預言機問題,它被廣泛稱作整條鏈上最薄弱的一環。
答案,正是當初讓鏈本身變得可信的那個念頭:不要依賴任何一個「單獨」的東西。現代的預言機並非孤身一人的報信者,而是一張由許多彼此獨立者組成的去中心化網路,每一個都各自去取那個事實、各自把它發布上來;合約隨後取它們的*中位數*,於是少數幾個說謊者或故障者,撼不動那個數字。如今要腐蝕真相,就意味著同時腐蝕其中的多數——代價高昂、顯眼難藏,且極不容易。信任並未消失,但已被攤得足夠薄,薄到安全。
小結
現在你已能如其所是地讀懂 Solidity:命名的狀態、人人可呼叫的函式,以及裁定誰能做什麼的 `require` 守衛。你也知道了這條鏈唯一真正的盲點——它只能就自己造出的事實達成一致,因此每一樁外部真相,都得靠一台區塊鏈預言機搬過那堵牆;而這恰恰是信任悄然重返之處,必須用守護鏈本身的那同一份去中心化,把它守住。
至此,我們對這條可程式化鏈的遊歷便告一段落——合約、EVM、gas、代幣,以及如今的 Solidity 與預言機。接下來,我們將向上爬一層,走進人們真正用這些零件搭起來的應用:借貸、無需中間人的交易、守住穩定價值的穩定幣,以及去中心化金融的其餘種種。