当前位置: 首页 > news >正文

call 与 delegatecall - all-in

一、为什么要用底层调用

我们知道,在一个合约中调用另一个合约的接口,通常使用contractName(address).functionName() 来进行调用,比如:

contract MyContract {function add(address _counter) public {// 调用 Counter 合约的方法Counter(_counter).increment();}
}

但是,有时我们在编写合约时,还不知道要调用的目标合约的接口,甚至是目标合约还没有创建。这时就无法用上面的方法进行调用。

这个问题该如何解决呢?

你也许知道很多编程语言(如Java和Go)有反射的概念,反射允许在运行时动态地调用函数或方法。地址的底层调用和反射非常类似。

使用address底层调用功能,是在运行时动态地决定调用目标合约和函数, 因此在编译时,可以不知道具体要调用的函数或方法。

二、底层调用

address类型还有3个底层的成员函数:

<address>.call(bytes memory abiEncodeData) returns (bool, bytes memory)<address>.delegatecall(bytes memory abiEncodeData) returns (bool, bytes memory)<address>.staticcall(bytes memory abiEncodeData) returns (bool, bytes memory)
  • 其中,call 是常规调用,delegatecall 为委托调用,staticcall 是静态调用(不修改合约状态, 相当于调用 view 方法)。

这三个函数都可以用于与目标合约<address>交互,三个函数均接受 abi 编码数据作为参数(abiEncodeData)来调用对应的函数。

这里我们使用底层方法调用一下《手把手教你部署智能合约》中的合约:

contract CallTest {function makeCallGet(address _counter) public view returns (uint) {// staticcall调用bytes memory payload = abi.encodeWithSignature("get()");(bool success, bytes memory returnData) = address(_counter).staticcall(payload);// 判断一下require(success, "Call to target contract failed.");// 将returnData解析成指定类型(e.g. uint)(uint res) = abi.decode(returnData, (uint));return res;}function makeCallCount(address _counter) public {// call调用bytes memory payload = abi.encodeWithSignature("count()");(bool success, ) = address(_counter).call(payload);// 判断一下require(success, "Call to target contract failed.");}
}// https://testnet.routescan.io/address/0xcF10C1b7DA166987a1D9bB81C072C339cb7205fd

使用底层方法调用合约函数时, 当被调用的函数发生异常时(revert),异常不会冒泡到调用者(即不会回退), 而是返回布尔值 false。因此在使用所有这些低级函数时,一定要记得检查返回值

三、call 与 delegatecall

常规调用 call 与 委托调用 delegatecall 的区别是什么呢?

image

  1. 执行上下文:当使用call函数时,被调用的函数在目标合约的上下文中执行,这意味着它有自己的thismsg.sender。而delegatecall函数则在调用合约(当前合约)的上下文中执行被调用的函数。—— 相当于将函数代码 pull 到当前合约中执行

  2. 状态存储call函数在执行时不会改变调用合约的状态,它只会改变被调用合约的状态。而delegatecall函数则可以改变调用合约的状态,因为它在调用合约的上下文中执行。

  3. 用途call函数通常用于调用其他合约的函数,而delegatecall函数允许一个合约借用另一个合约的代码,在自己的上下文中执行,常用于实现可升级合约和库函数。

http://www.jsqmd.com/news/47829/

相关文章:

  • 20232417 2025-2026-1 《网络与系统攻防技术》实验六实验报告
  • Trick——字符串
  • 2022年春季研究资助计划征集技术提案
  • BLOG-1-电梯调度算法
  • 线圈公司质量排名,线圈生产厂家性价比推荐,变压器公司行业排名,变压器生产厂家客户推荐。滤波器公司技术排名,开关变压器公司性价比榜单
  • IDA之修复结构体
  • 2025年专业集成房屋安装公司排名,集成活动房十大靠谱厂家推荐榜,石家庄集成房屋公司十大排行:义广达彩钢口碑推荐榜,河北集成活动房厂家十大推荐榜
  • 真的好怪题解:P14314 [Aboi Round 2] Oneshot
  • ElasticSearch索引库操作 - 努力-
  • 2025年集成房屋设计公司十大排名,岗亭加工厂家十大排行榜,专业岗亭定制工厂怎么选?彩钢移动厕所厂家推荐。
  • 礼盒拖车公司推荐,礼盒拖车定制公司排行榜,礼盒拖车厂家口碑推荐,礼盒拖车生产厂家-航利通达
  • 360笔试
  • 图像的颜色模式
  • .NET+AI | MEAI | Function Caling 实操(4)
  • 高频变压器公司口碑榜单,电感公司技术排名,电感厂家交付效率排名,磁性元器件公司客户推荐,电感器公司产能排名,线圈公司行业排名-汉翔电子
  • MinIo介绍 - 努力-
  • BLOG1
  • host with linux
  • sguardsvc64.exe(Anti-Cheat Expert)驱动不兼容导致无法开启“内核模式硬件强制堆栈保护”或“内存完整性”
  • Wi-Fi FTM 技术 10 年后展望
  • Docker使用【镜像】 - 指南
  • 20251122
  • 2025年11月22日训练赛
  • Python 潮流周刊#128:将 Rust 语言引入 CPython
  • NCHU_单部电梯调度程序总结blogs
  • 电梯调度程序分析
  • Hive动态分区怎样减少存储压力
  • 面向对象程序设计——单元总结
  • Linux命令绕过 - 教程
  • 帮同学签了个到,我发现竟然能盗光他所有账号