解讀stETH的巧妙設計,它是如何按天自動發放收益的?
BlockBeats 律動財經 2024-03-11 21:00
筆者把自己為數不多的 ETH 兌換為 stETH 後,發現 stETH 每天都在自然增長,不斷獲取收益。但是卻沒有看到帳戶有交易產生,這是為什麼呢?本文帶大家一起來看看背後的巧妙設計,揭開收益發放的秘密。
在這之前先介紹一下 stETH 賺取收益背後的邏輯,也就是以太坊的質押(Staking),已經了解這部分概念的讀者可以直接跳到後面。
最初的以太坊和比特幣一樣是通過工作量證明(Proof of Work,PoW)來作為它的共識機制,但是 PoW 因為耗電以及其它安全性和性能上發展的考慮,以太坊從 2022 年 9 月開始升級為權益證明(Proof of Stake,PoS)。
原本依靠算力挖礦來吸引礦工實現共識的以太坊,搖身一變,變成了依靠大家通過質押 ETH 獲取投票權,通過投票來獲取收益,從而激勵大家通過 PoS 的方式來實現共識。
通過質押 32 個 ETH 可以加入以太坊網路,可以成為驗證者,負責儲存數據、處理交易以及向區塊鏈添加新區塊。只要運行將交易正確打包為新區塊並檢查其他驗證者工作,就會獲得 ETH 獎勵,這樣就相當於你可以通過質押的方式讓 ETH 可以擁有相對穩定的收益。
但是這樣的質押對於普通用戶來說還是太麻煩,畢竟 32 個以太坊和一台要能夠全年無休接入以太坊網路的專用計算機還是有一定的門檻的。而且質押 ETH 會使得喪失了這部分 ETH 的流動性。於是就有了流動性質押衍生品(Liquid Staking Derivatives,LSD),它旨在解決傳統質押中的門檻和流動性問題,允許用戶質押 32 個以下的 ETH,以及不需要自己擁有節點,而是把 ETH 委託給第三方質押,並獲取相應的質押代幣(如 Lido 的 stETH 或 Rocket Pool 的 rETH),這些流動性代幣可以在其他平台上交易、借貸或用於其他金融活動,這樣,用戶既能更便捷參與到質押中獲得獎勵,又能保持資金的靈活性。
所以 stETH 本質的邏輯就是把 ETH 給到 Lido,Lido 會用這些 ETH 去參與以太坊的 PoS 以獲取收益,用戶會得到對應的 stETH 作為憑證。接下來就是 Lido 要把收益發放給這些擁有 stETH 的地址。
我們可以看到 stETH 的收益每天都會自動更新,下圖是我們測試的收益情況,對應每天都可以檢查加密錢包驗證相關內容。
但是到這裡我想熟悉智能合約開發的同學就會疑惑了:每天發放這麼少的收益,可能收益都不夠付 GAS 的。
確實,如果 Lido 按照最簡單的做法來發放收益的話,那確實難以覆蓋 GAS 的成本。從我們的直覺來看,要往如此眾多的地址發送代幣,GAS 是難以想象的。
但是確實 Lido 就實現了錢包中的 stETH 收益自動增長,而且我們並沒有發現該地址有任何交易,這是怎麼實現的呢?
我們找到了 Lido 的合約 https://etherscan.io/token/0xae7ab96520de3a18e5e111b5eaab095312d7fe84 追溯到合約的 balanceOf 方法:
balanceOf 是符合 ERC20 規範的方法,錢包就是通過該方法獲取用戶有多少 token 的。
我們可以看到 stETH 的合約中這裡調用了 getPooledEthByShares 方法。該方法入參是 mapping (address => uint256) private shares;。這代表用戶有多少 stETH?顯然不是,不然每天都需要更新每個地址的數據,雖然這樣也可以做到只要調用合約中的方法來更新 shares 來實現一次交易就能更新所有地址的 token,但是顯然這樣做 GAS 的消耗同樣也是巨大的。
想必到這裡大家已經要猜到合約是怎麼實現的了,我們繼續來看 getPooledEthByShares 方法。
可以看到最終返回的結果是用地址中 sharesAmount 乘以 _getTotalPooledEther() 再除 _getTotalShares。
_getTotalPooledEther 代表總共有多少 stETH(按照 stETH 兌 ETH 為 1:1 的話也代表有多少 ETH),_getTotalShares 代表有多少市佔率。這樣一算每個地址有多少 stETH 就是動態計算出來的了。
舉例說如果現在一共有 1000 個市佔率(Shares,也就是 _getTotalShares 方法返回的數量),其中 A 地址有 100 份(對應上面的 sharesAmount)。這 1000 個市佔率對應 1000 個 stETH(也就是 _getTotalPooledEther)返回的數量。那麼按照這個計算,A 地址就對應有 100 個 stETH。那 Lido 拿這總得 1000 個 ETH 去質押獲取到 1 個 ETH 的收益後對應更新 _getTotalPooledEther 為 1001,也就是最初總共 1000 個的 stETH 變多變成 1001 個了,那麼新的計算出來 A 地址就擁有了 100 * 1001 / 1000 = 100.1 個 stETH。
簡單點說就是每個地址擁有的股份不變,股份對應的 stETH 變多了,那麼一計算自然 stETH 就變多了。
我們繼續看代碼, _getTotalPooledEther 中的邏輯是會受到 handleOracleReport 方法影響,而這個方法則會更新合約中的相關數據。具體的調用是會通過 https://etherscan.io/address/0x852deD011285fe67063a08005c71a85690503Cee 合約定期調用 submitReportData 更新數據(submitReportData 中會調用 Lido 合約的 handleOracleReport):
我們可以看到每天都會有調用更新相關內容,這就是為什麼雖然我們無法看到我們的地址中有發放收益的交易,但是金額依然每天在變化的原因。
這背後其實體現了以太坊 ERC20 智能合約的一個特點,就是這些 ERC20 的合約擁有多少代幣並不是寫死在地址上的,而是合約方法返回的,所以可能會出現賬號雖然沒有任何交易,但是代幣的數量也可能發生變化。這一方面讓 ERC20 合約更靈活,但是另外一方面也給很多對合約不熟悉的朋友帶來了很多困惑,希望本文可以幫助大家更多的理解智能合約,更安全的和智能合約交互。
另外,雖然通過把 ETH 質押為 stETH 能夠獲得看似穩定的質押收益,但是依然有可能的風險存在,本文只作為對質押合約的技術研究參考,不構成任何投資建議。
暢行幣圈交易全攻略,專家駐群實戰交流
▌立即加入鉅亨買幣實戰交流 LINE 社群(點此入群)
不管是新手發問,還是老手交流,只要你想參與虛擬貨幣現貨交易、合約跟單、合約網格、量化交易、理財產品的投資,都歡迎入群討論學習!
- 加入鉅亨買幣LINE官方帳號索取免費課程
- 掌握全球財經資訊點我下載APP
文章標籤
上一篇
下一篇