web3区块链-小镇店铺的 “借力办事”:call 与 delegatecall 的区别与联系Web3-智能合约-整数溢出攻击:“凭空造币”的秘密

作者:想ai抽日期:2025/12/4

加密小镇上有两家店:

  • A 店(水果店):老板是 Alice,有自己的账本(合约存储),记录着 “苹果库存”(存储变量uint256 public appleStock = 100;),但没学会 “盘点库存”“修改库存” 的方法;
  • B 店(管理咨询店):老板是 Bob,专门帮人做库存管理,有两套核心 “操作手册”(合约函数):
    1. checkStock():读取自己账本上的库存,返回数值;
    2. addStock(uint256 num):把自己账本上的库存增加num个。

A 店想复用 B 店的方法,不用自己写代码 —— 这就对应 Solidity 里合约间的两种调用方式:calldelegatecall

一、先看 “联系”:都是 “借力办事”,复用他人逻辑

不管是call还是delegatecall,核心目的都是让 A 店(调用方合约)借用 B 店(被调用方合约)的代码逻辑,不用自己重复开发。就像 A 店不用自己学盘点方法,直接请 B 店的人来 “帮忙操作”,本质都是 “复用他人功能”。

另外,两者的基础规则一致:

  • 都会传递msg.sender(调用者身份,比如 Alice 发起调用,msg.sender就是 Alice)和msg.value(附带的 ETH);
  • 都需要知道 B 店的地址和函数签名(比如checkStock()的签名是0x123...);
  • 都是合约间交互的核心方法,属于低级别调用(区别于合约实例.函数名()的高级调用)。

二、核心区别:“借方法时,用谁的账本?”

这是calldelegatecall的本质差异 ——调用方是否使用自己的存储(账本)执行被调用方的代码

场景 1:call 调用 ——“借你的方法,算你的账”

Alice 想让 B 店帮忙 “盘点库存”,用了call方式:

  1. Alice 对 B 店说:“麻烦用你的checkStock()方法,帮我看看库存有多少?”
  2. B 店收到请求后,拿出自己的账本(B 店的存储),发现自己的 “苹果库存” 是 0(B 店本来不存水果),于是回复 Alice:“库存是 0”;
  3. 后续 Alice 又用call调用 B 店的addStock(50)
    • B 店还是用自己的账本,把自己的库存从 0 改成 50;
    • A 店的账本丝毫没变化,苹果库存依然是 100。

对应 Solidity 逻辑

1// A店合约(调用方)
2contract ShopA {
3    uint256 public appleStock = 100; // A店自己的库存(账本)
4
5    function callBCheckStock(address shopB) external returns (uint256) {
6        // call调用B店的checkStock(),用B店的存储
7        (bool success, bytes memory data) = shopB.call(abi.encodeWithSignature("checkStock()"));
8        require(success, "call failed");
9        return abi.decode(data, (uint256)); // 返回B店的库存(0)
10    }
11
12    function callBAddStock(address shopB) external {
13        // call调用B店的addStock(50),修改B店的存储
14        shopB.call(abi.encodeWithSignature("addStock(uint256)", 50));
15    }
16}
17
18// B店合约(被调用方)
19contract ShopB {
20    uint256 public appleStock = 0; // B店自己的库存(账本)
21
22    function checkStock() external view returns (uint256) {
23        return appleStock; // 读取B店的存储
24    }
25
26    function addStock(uint256 num) external {
27        appleStock += num; // 修改B店的存储
28    }
29}
30

call 的核心特点:被调用方(B 店)的代码,操作的是被调用方自己的存储,调用方(A 店)的存储完全不受影响 —— 相当于 “借别人的工具,修别人的东西”。

场景 2:delegatecall 调用 ——“借你的方法,修我的账”

Alice 觉得call没用(改的是 B 店的库存),于是换了delegatecall方式:

  1. Alice 对 B 店说:“麻烦用你的checkStock()方法,但帮我查我自己的账本!”
  2. B 店收到请求后,没有拿自己的账本,而是拿起A 店的账本(A 店的存储),读取 A 店的苹果库存 100,回复 Alice:“库存是 100”;
  3. 后续 Alice 用delegatecall调用 B 店的addStock(50)
    • B 店依然用 A 店的账本,把 A 店的库存从 100 改成 150;
    • B 店自己的账本还是 0,丝毫没变化。

对应 Solidity 逻辑(B 店合约不变,A 店调用方式改):

1contract ShopA {
2    uint256 public appleStock = 100; // A店自己的库存(账本)
3
4    function delegateCallBCheckStock(address shopB) external returns (uint256) {
5        // delegatecall调用B店的checkStock(),用A店的存储
6        (bool success, bytes memory data) = shopB.delegatecall(abi.encodeWithSignature("checkStock()"));
7        require(success, "delegatecall failed");
8        return abi.decode(data, (uint256)); // 返回A店的库存(100)
9    }
10
11    function delegateCallBAddStock(address shopB) external {
12        // delegatecall调用B店的addStock(50),修改A店的存储
13        shopB.delegatecall(abi.encodeWithSignature("addStock(uint256)", 50));
14    }
15}
16

delegatecall 的核心特点:被调用方(B 店)的代码,操作的是调用方(A 店)的存储—— 相当于 “借别人的工具,修自己的东西”。

⚠️ 关键注意点:delegatecall要求 “调用方和被调用方的存储结构对齐”!比如 A 店和 B 店都必须有uint256 public appleStock(且变量顺序一致),否则会读取 / 修改错误的存储位置(比如把 A 店的其他变量当成库存改了)。

三、区别与联系总结表

维度calldelegatecall
核心联系均为合约间低级别调用,复用被调用方代码逻辑,传递 msg.sender/msg.value
操作的存储被调用方(B 店)的存储调用方(A 店)的存储
核心用途调用其他合约的功能,且需要修改对方的状态(比如调用 Uniswap 的 swap 函数,修改 Uniswap 的流动性)复用通用逻辑(如权限校验、数学计算),且需要修改自身状态(比如多个合约共用 “修改所有者” 的逻辑,用 delegatecall 调用代理合约的代码,修改自身的 owner)
存储要求无强制对齐要求(调用方和被调用方存储可不同)必须对齐存储结构(变量类型、顺序一致),否则会出现存储错乱
场景类比请维修师傅用他的工具,修他的设备请维修师傅用他的工具,修你的设备

四、真实开发中的典型场景

  1. call 的常见场景
    • 调用其他 DApp 的合约功能(比如调用 USDT 的transfer转账,修改 USDT 合约中的余额记录);
    • 批量执行多个合约操作(比如一次调用多个合约的查询方法)。
  2. delegatecall 的常见场景
    • 代理模式(Proxy Pattern):比如升级合约时,代理合约(用户交互的合约)用delegatecall调用逻辑合约(存储业务代码),确保用户数据始终存在代理合约中,逻辑合约可替换;
    • 通用逻辑复用(比如多个合约都需要 “只有管理员能操作” 的权限校验,把校验逻辑写在一个 “权限合约” 里,其他合约用delegatecall调用,修改自身的管理员状态)。

简单说:call是 “帮别人办事”,delegatecall是 “请别人帮自己办事”—— 核心区别就在 “办事时用谁的账本(存储)”。

Web3-智能合约-整数溢出攻击:“凭空造币”的秘密


web3区块链-小镇店铺的 “借力办事”:call 与 delegatecall 的区别与联系Web3-智能合约-整数溢出攻击:“凭空造币”的秘密》 是转载文章,点击查看原文


相关推荐


告别AI塑料感:阿里Qwen3-Omni-Flash要把大模型做成真人
墨风如雪2025/12/13

如果是长期关注大模型领域的朋友,大概都会有这样一种感觉:现在的AI虽然智商越来越高,但只要一开口说话,那种特有的“塑料感”还是很难消除。无论是语音的机械停顿,还是多模态交互时的“脑子慢半拍”,都时刻提醒着我们,对面只是个程序。 但在2025年12月9日,这个局面似乎被阿里的Qwen团队撕开了一道口子。 他们正式发布的Qwen3-Omni-Flash-2025-12-01,不再仅仅是在刷榜单上的分数(虽然分数确实也刷得很猛),而是实打实地盯着“像人一样交流”这件事死磕。作为一名在这个圈子里摸爬滚打


flink的一阶段提交的流程
飞哥大数据2025/12/21

Flink的一阶段提交流程 Apache Flink 是一个分布式流处理框架,用于高效处理大规模数据流。在 Flink 中,“提交”通常指将作业部署到集群执行的过程。用户提到的“一阶段提交”可能指的是 Flink 中某些特定场景下的简化提交机制,尤其是在事务处理或 Sink 端(输出端)的 Exactly-Once 语义实现中。标准 Flink 作业提交涉及多个步骤,但“一阶段提交”更常见于事务管理上下文,例如当 Sink 系统支持幂等操作时,Flink 可以使用一阶段提交来简化流程,避免两阶


2025年12月总结
袁庭新2025/12/31

大家好,我是袁庭新。2025年的最后一个月已经圆满结束,借此机会对本月的工作进行一次总结与回顾。 课程研发 一直想讲一门如何赚钱的课,这就是《微信商业生态平民创业》这门课设计的初衷,这个月编写了2节这门课的讲义,但还未完成录制,现总计录制了20节,计划是24节课程。 放在以前软件开发和我们绝大多数人是没有关系,随着大模型基础服务平台的崛起,你可能无法想象现在不懂任何编程技术零基础也可快速上手定制开发出自己的智能体应用出来,并上线到各大平台,如微信小程序、豆包等。 这个月我也集中注意力开发了7个实


微服务架构核心组件、职责与交互全解析
元Y亨H2026/1/8

微服务架构核心组件、职责与交互全解析 一、 微服务全景架构图(分层) 微服务不再是散乱的工程,而是一个分工明确的矩阵。通过分层,我们可以更清晰地看到请求是如何流转的。 ==================== 流量接入层 (Entrance) ==================== [ 外部客户端:App / H5 / Web / PC ] │ (Restful API / HTTPS) ┌───────


Mac 科研/论文专用快捷键(Word + LaTeX + Finder) 与文件管理
加油_Yeah2026/1/16

✅ 一、只背 15 个的「Mac 生存快捷键」 只记这 15 个,就能高效 + 不踩坑 🔑 核心通用(8 个) ⌘ + Space —— 全局搜索(秒开文件/程序) ⌘ + Z —— 撤销(后悔药) ⌘ + ⇧ + Z —— 重做 ⌘ + C —— 复制 ⌘ + V —— 粘贴 ⌘ + ⌥ + V —— 移动文件(重点) ⌘ + S —— 保存 ⌘ + Q —— 彻底退出程序 📁 文件 / 窗口(7 个) ⌘ + ⇧ + N


拥抱PostgreSQL支持UI配置化
神奇的程序员2026/1/25

前言 前阵子写的日志分析工具NginxPulse,自开源以来,已过去2周时间,目前GitHub已收获1.5k的star。收到了不少用户的反馈建议,花了点时间将这些问题都处理了下。 本文就跟大家分享下新版本都解决了哪些问题,优化了哪些内容,欢迎各位感兴趣的开发者阅读本文。 抛弃SQLite 有不少用户反馈说日志文件很大的时候(10G+),解析速度非常慢,需要解析好几个小时,解析完成之后数据看板的查询也比较慢(接口响应在5秒左右)。 于是,我重写了日志解析策略(解析阶段不做IP归属地查询,仅入库其他


Node.js 自带“加速器”:node --run 是否比 Bun 更快?
Legend80s2026/2/3

前言 在 JavaScript 后端运行时领域,速度一直是核心战场。近年来,Bun 以其宣称的“一体化”工具链和闪电般的启动速度异军突起,对老牌王者 Node.js 发起了强劲挑战。bun run 的迅捷,让许多开发者开始重新评估他们的工具选择。 然而,Node.js 并未止步。自 v22.0.0 起,它悄然引入了一个专为启动性能而生的秘密武器:node --run。这个内置于 Node.js 核心的命令,旨在以最精简、最直接的方式执行 package.json 中的脚本,宣称要为最常见的用例提


【C++】c++中“引用”的详解
王璐WL2026/2/12

文章目录 1. 引用1.1 引用的概念和定义1.2 引用的特性1.3 引用的使用小小的延伸1.4 const引用1.5 指针和引用的关系(面试常考) 1. 引用 1.1 引用的概念和定义 ​ 引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间(指针会开辟空间), 它和它引⽤的变量共⽤同⼀块内存空间。比如:水浒传中林冲,外号豹⼦头 ​ 类型&引⽤别名=引⽤对象; ​ C++中为了避免引⼊太多的运算符,会复⽤C语⾔的⼀些符号,⽐如前⾯


Hadoop MapReduce 详解
之歆2026/2/20

想象一个巨大的文档分类任务,一个人处理要一个月。MapReduce 把这个任务分配给一百个人,每人处理一小部分,最后把结果汇总,半小时就完成了!这就是 MapReduce 的威力! 📑 目录 MapReduce 概述名词解释(命令与术语)Map 阶段详解Shuffle 阶段详解Reduce 阶段详解完整 WordCount 示例高级特性MapReduce 与 YARN监控与调试性能优化总结官方文档与参考 🎯 MapReduce 概述 什么是 MapReduce? Map


我的“龙虾”罢工了!正好对比下GLM、MiniMax、Kimi 3家谁更香
飞哥数智谈2026/3/1

OpenClaw(中文名:龙虾,曾用名:Clawdbot、Moltbot)从年底到现在热度持续飙升,而我感觉自己使用的还有些浅,没好意思写相关的内容。 结果今天我的龙虾罢工了,看了下,发现模型的 Coding Plan 到期了。 那正好了解下目前国内几家 Coding Plan 的内容,也方便大家对比。 本文仅涉及 GLM、Minimax、Kimi 3家自有产品的订阅套餐对比,像火山引擎、千问、无问芯穹类的综合套餐未加入对比。 为了方便对比,所有套餐都是采用按月 快速对比 核心指标整理到一

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客