web3区块链-小镇店铺的 “借力办事”:call 与 delegatecall 的区别与联系

加密小镇上有两家店:

  • 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 逻辑

复制代码
// A店合约(调用方)
contract ShopA {
    uint256 public appleStock = 100; // A店自己的库存(账本)

    function callBCheckStock(address shopB) external returns (uint256) {
        // call调用B店的checkStock(),用B店的存储
        (bool success, bytes memory data) = shopB.call(abi.encodeWithSignature("checkStock()"));
        require(success, "call failed");
        return abi.decode(data, (uint256)); // 返回B店的库存(0)
    }

    function callBAddStock(address shopB) external {
        // call调用B店的addStock(50),修改B店的存储
        shopB.call(abi.encodeWithSignature("addStock(uint256)", 50));
    }
}

// B店合约(被调用方)
contract ShopB {
    uint256 public appleStock = 0; // B店自己的库存(账本)

    function checkStock() external view returns (uint256) {
        return appleStock; // 读取B店的存储
    }

    function addStock(uint256 num) external {
        appleStock += num; // 修改B店的存储
    }
}

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 店调用方式改):

复制代码
contract ShopA {
    uint256 public appleStock = 100; // A店自己的库存(账本)

    function delegateCallBCheckStock(address shopB) external returns (uint256) {
        // delegatecall调用B店的checkStock(),用A店的存储
        (bool success, bytes memory data) = shopB.delegatecall(abi.encodeWithSignature("checkStock()"));
        require(success, "delegatecall failed");
        return abi.decode(data, (uint256)); // 返回A店的库存(100)
    }

    function delegateCallBAddStock(address shopB) external {
        // delegatecall调用B店的addStock(50),修改A店的存储
        shopB.delegatecall(abi.encodeWithSignature("addStock(uint256)", 50));
    }
}

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

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

三、区别与联系总结表

维度 call delegatecall
核心联系 均为合约间低级别调用,复用被调用方代码逻辑,传递 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-智能合约-整数溢出攻击:"凭空造币"的秘密

相关推荐
光影少年3 小时前
web3学习路线
前端·学习·前端框架·web3
想ai抽3 小时前
web3区块链-加密小镇的 “十年庆典徽章”:ERC-721 全流程故事(含所有核心接口)
web3·区块链·nft
Web3VentureView3 小时前
Synbo 产品发布会在吉隆坡举行:重构 Web3 一级市场融资模式
网络·人工智能·重构·web3·区块链·synbo
leijiwen15 小时前
Bsin X BDCM:从流量驱动到价值激励驱动的智能增长引擎
大数据·人工智能·web3
1***y17815 小时前
Web3.0在去中心化社交的隐私保护
web3·去中心化·区块链
1***y17816 小时前
区块链跨链桥、 跨链桥到底在解决什么问题?
大数据·人工智能·区块链
小小码农一只17 小时前
AI与区块链结合的未来:数据安全与去中心化应用的探索
人工智能·去中心化·区块链
x***B41118 小时前
区块链在金融中的Cardano
金融·区块链
4***997418 小时前
区块链在金融中的去中心化交易所
金融·去中心化·区块链