尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

call 与 delegatecall - all-in

call 与 delegatecall - all-in
📅 发布时间:2026/6/20 6:56:51

一、为什么要用底层调用

我们知道,在一个合约中调用另一个合约的接口,通常使用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函数时,被调用的函数在目标合约的上下文中执行,这意味着它有自己的this和msg.sender。而delegatecall函数则在调用合约(当前合约)的上下文中执行被调用的函数。—— 相当于将函数代码 pull 到当前合约中执行

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

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

相关新闻

  • 洛谷 P5658 [CSP-S 2019] 括号树 题解
  • .NET+AI | MEAI | Function Caling 实操(4)
  • Java中HashMap的核心原理与使用注意事项

最新新闻

  • 软件测试基础:黑盒、白盒、灰盒测试
  • 2026年工业工厂吸尘器Top3:Shiwosi史沃斯凭什么第一? - 工业清洁测评社
  • 多智能体系统中的向量化声誉传播机制TrustFlow解析
  • Qwen3vl多模态后训练实战:LLamaFactory深度适配指南
  • 国产MLU算网+LLaMA-Factory:零代码微调百余大模型实战指南
  • 猫抓插件:3步搞定浏览器资源嗅探的终极指南

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号