当前位置:网站首页>可昇級合約的原理-DelegateCall
可昇級合約的原理-DelegateCall
2022-07-02 11:35:00 【灬倪先森_】
可昇級合約的原理-DelegateCall
在介紹DelegateCall時,我們需要帶上Call方法一起介紹,並做對比。
先說概念吧!
DelegateCall:有一種特殊類型的消息調用,被稱為 委托調用(delegatecall) 。它和一般的消息調用(call)的區別在於,目標地址的代碼將在發起調用的合約的上下文中執行,並且 msg.sender 和 msg.value 不變。 這意味著一個合約可以在運行時從另外一個地址動態加載代碼。
我不喜歡一上來就講概念,畢竟太難理解。還是上代碼演示吧
演示環境
Remix IDE:Remix是基於瀏覽器的 IDE,集成了編譯器和 Solidity 運行時環境,不需要服務端組件,支持網頁在線編寫、部署和測試智能合約。
本章主要是讓大家快速了解DelegateCall的特性,所以選擇基於Remix來演示。
編碼
我們在contracts目錄下新建delegatecall.sol文件,並接下來把下面演示代碼粘貼進delegatecall.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract A {
address public msgsender;
function callFunc() public {
msgsender = msg.sender;
}
}
contract B {
address public msgsender;
address public a;
constructor(address _a) {
a = _a;
}
function call_a_call() public{
// isOk 用來接收調用是否成功
(bool isOk,bytes memory result) = a.call(abi.encodeWithSignature("callFunc()"));
// 如果失敗,報异常
require(isOk,"call faild");
}
function delegatecall_a_delegatecall() public{
(bool isOk,bytes memory result) = a.delegatecall(abi.encodeWithSignature("callFunc()"));
require(isOk,"call faild");
}
}
我們在這裏定義兩個合約A和B
A合約有一個msgsender狀態變量和callFunc()方法
B合約有兩個狀態變量msgsender和a,msgsender是為了驗證我們的實驗結果,a是存放合約A的實例引用,並且定義了兩個方法,分別用來演示用B合約通過call和delegatecall兩種方式調用A合約的callFunc()
然後我們按Ctrl + s快捷鍵,這裏會保存合約代碼,編譯器會自動幫我們編譯
合約部署
點擊下面的按鈕跳轉到部署與調試頁面
先部署合約A,再部署合約B,因為B中的狀態變量a引用了A的地址
- 部署合約
A
- 部署合約
B
部署合約B時需要傳入A的地址
合約交互
我們先點擊>按鈕展開我們的合約,並點擊A合約和B合約的msgsender按鈕查詢(點擊按鈕會自動調用msgsender的查詢方法)當前狀態變量的值,這裏我們可以看到都為0
接下來我們點擊B合約delegatecall_a_delegatecall按鈕(調用delegatecall_a_delegatecall方法),然後再次點擊A合約和B合約的msgsender按鈕查詢
奇怪的事情發生了!!!A合約的msgsender沒有值,但是B合約的msgsender變成了我自己的地址0x5B38Da6a....
好了,我們可以結合上面的實驗結果,再來理解文章開頭的所說的概念
目標地址A合約的代碼將在發起調用的B合約的上下文中執行,並且 msg.sender 和 msg.value 不變。上下文就是運行環境,就包括了合約裏的狀態變量,所以當合約執行callFunc()的內容時,callFunc()方法是在B合約裏執行的,修改的是B合約的狀態變量,而A合約的msgsender卻沒有變化。
如果B合約的兩個狀態變量msgsender和a在代碼中互換比特置,就是另一個故事了,這裏涉及到另一個概念《合約數據存儲布局》
接下來我們點擊B合約call_a_call按鈕,然後再次點擊A合約和B合約的msgsender按鈕查詢
現在A合約的msgsender有值了,B合約的msgsender值沒有變化。
當調用B合約call_a_call方法時,B合約的狀態變量沒有發生變化,A合約的msgsender有值了,這說明callFunc()方法是在A合約的上下文環境中執行的,這裏上下文發生了變化。
並且我們發現A合約的msgsender變成了B合約的地址,這說明在調用的過程中msg.sender 和 msg.value發生了變化,msg.sender 不再是我自己0x5B38Da6a....而是B合約的地址
總結
會顧我們前面寫的可昇級合約,當對代理合約發起調用時,代理合約與邏輯合約交互就是用的委托調用(DelegateCall)。邏輯合約的方法在代理合約的上下文執行,並且修改的狀態變量也是代理合約的。所以合約數據一直都在代理合約裏,當邏輯合約昇級時並不會影響合約原來已有的數據
有問題,或者建議請留言,謝謝。
边栏推荐
- Some suggestions for young people who are about to enter the workplace in the graduation season
- RPA进阶(二)Uipath应用实践
- Eight sorting summaries
- Summary of data export methods in powerbi
- Openmldb meetup No.4 meeting minutes
- SSRF
- 数字化转型挂帅复产复工,线上线下全融合重建商业逻辑
- Iii. Système de démarrage et d'horloge à puce
- II Stm32f407 chip GPIO programming, register operation, library function operation and bit segment operation
- Calculate the sum of sequences
猜你喜欢

Verilog and VHDL signed and unsigned number correlation operations

Webauthn - official development document

【云原生】2.5 Kubernetes 核心实战(下)

Multi line display and single line display of tqdm

亚马逊云科技 Community Builder 申请窗口开启

Basic usage of MySQL in centos8

mmrotate旋转目标检测框架使用记录

TIPC Cluster5

Never forget, there will be echoes | hanging mirror sincerely invites you to participate in the opensca user award research

TIPC addressing 2
随机推荐
spritejs
二.Stm32f407芯片GPIO编程,寄存器操作,库函数操作和位段操作
String (Analog
STM32单片机编程学习
TIPC 寻址2
[play with FPGA learning 5 in simple terms ----- reset design]
Multi line display and single line display of tqdm
Never forget, there will be echoes | hanging mirror sincerely invites you to participate in the opensca user award research
sqlite 修改列类型
Approximate sum count (approximate
Eight sorting summaries
TIPC addressing 2
SSRF
PKG package manager usage instance in FreeBSD
LVM操作
在连接mysql数据库的时候一直报错
JS -- take a number randomly from the array every call, and it cannot be the same as the last time
deepTools对ChIP-seq数据可视化
ros缺少xacro的包
MTK full dump grab