menu-icon
anue logo
熱門時事鉅亨號鉅亨買幣
search icon

區塊鏈

Solidity極簡入門|第二十三講:Delegatecall

BlockBeats 律動財經 2022-08-25 20:30

cover image of news article
律動財經圖片

我最近在重新學 solidity,鞏固一下細節,也寫一個「Solidity 極簡入門」,供小白們使用(編程大佬可以另找教程),每周更新 1-3 講。

所有代碼和教程開源在 github:github.com/AmazingAng/WTFSolidity

delegatecall

delegatecall 與 call 類似,是 solidity 中地址類型的低級成員函數。delegate 中是委託/代表的意思,那麼 delegatecall 委託了什麼?


當用戶 A 通過合約 B 來 call 合約 C 的時候,執行的是合約 C 的函數,語境 (Context,可以理解為包含變量和狀態的環境) 也是合約 C 的:msg.sender 是 B 的地址,並且如果函數改變一些狀態變量,產生的效果會作用於合約 C 的變量上。

  call 的語境


而當用戶 A 通過合約 B 來 delegatecall 合約 C 的時候,執行的是合約 C 的函數,但是語境仍是合約 B 的:msg.sender 是 A 的地址,並且如果函數改變一些狀態變量,產生的效果會作用於合約 B 的變量上。 



delegatecall 的語境 


大家可以這樣理解:一個富商把它的資產(狀態變量)都交給一個 VC 代理(目標合約的函數)來打理。執行的是 VC 的函數,但是改變的是富商的狀態。

delegatecall 語法和 call 類似,也是:    





  其中二進制編碼利用結構化編碼函數 abi.encodeWithSignature 獲得:





函數簽名為"函數名(逗號分隔的參數類型)"。例如 abi.encodeWithSignature("f(uint256,address)", _x, _addr)。

和 call 不一樣,delegatecall 在調用合約時可以指定交易發送的 gas,但不能指定發送的 ETH 數額

注意:delegatecall 有安全隱患,使用時要保證當前合約和目標合約的狀態變量儲存結構相同,並且目標合約安全,不然會造成資產損失。

什麼情況下會用到 delegatecall?

目前 delegatecall 主要有兩個應用場景:

代理合約(Proxy Contract):將智能合約的儲存合約和邏輯合約分開:代理合約(Proxy Contract)儲存所有相關的變量,並且保存邏輯合約的地址;所有函數存在邏輯合約(Logic Contract)里,通過 delegatecall 執行。當升級時,只需要將代理合約指向新的邏輯合約即可。

EIP-2535 Diamonds(鑽石):鑽石是一個支持構建可在生產中擴展的模塊化智能合約系統的標準。鑽石是具有多個實施合約的代理合約。更多資訊請查看:鑽石標準簡介。

delegatecall 例子

調用結構:你(A)通過合約 B 調用目標合約 C。

被調用的合約 C

我們先寫一個簡單的目標合約 C:有兩個 public 變量:num 和 sender,分別是 uint256 和 address 類型;有一個函數,可以將 num 設定為傳入的_num,並且將 sender 設為 msg.sender。



發起調用的合約 B

首先,合約 B 必須和目標合約 C 的變量儲存布局必須相同,兩個變量,並且順序為 num 和 sender



接下來,我們分別用 call 和 delegatecall 來調用合約 C 的 setVars 函數,更好的理解它們的區別。

callSetVars 函數通過 call 來調用 setVars。它有兩個參數_addr 和_num,分別對應合約 C 的地址和 setVars 的參數。



而 delegatecallSetVars 函數通過 delegatecall 來調用 setVars。與上面的 callSetVars 函數相同,有兩個參數_addr 和_num,分別對應合約 C 的地址和 setVars 的參數。  





運行結果

我們把合約 B 和 C 都部署好,然後調用合約 C 中的 callSetVars,傳入參數為合約 B 地址和 10。運行後,合約 C 中的狀態變量將被修改:num 被改為 10,sender 變為合約 B 的地址。

接下來,我們調用合約 C 中的 delegatecallSetVars,傳入參數為合約 B 地址和 100。由於是 delegatecall,語境為合約 B。在運行後,合約 B 中的狀態變量將被修改:num 被改為 100,sender 變為合約你的錢包地址。

總結

這一講我們介紹了 solidity 中的另一個低級函數 delegatecall。與 call 類似,它可以用來調用其他合約;不同點在於運行的語境,B call C,語境為 C;而 B delegatecall C,語境為 B。目前 delegatecall 最大的應用是代理合約和 EIP-2535 Diamonds(鑽石)。

原文連結

暢行幣圈交易全攻略,專家駐群實戰交流

▌立即加入鉅亨買幣實戰交流 LINE 社群(點此入群
不管是新手發問,還是老手交流,只要你想參與虛擬貨幣現貨交易、合約跟單、合約網格、量化交易、理財產品的投資,都歡迎入群討論學習!

前往鉅亨買幣找交易所優惠

文章標籤


Empty