You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keeper合约调用delegatecall修改ContractB状态变量失效问题

问题根源

你混淆了delegatecall和普通call的使用场景,这是出现问题的核心原因:

  • delegatecall的运行机制是借用目标合约的代码,在当前发起调用的合约(也就是Counter合约)的存储上下文中执行,所有状态读写、事件触发都作用在Counter合约上,完全不会修改目标ContractB的任何状态。你现在看到的事件触发地址实际上是Counter合约地址,而非ContractB地址,ContractB本身的tokenName变量没有任何改动。
  • 你如果想修改ContractB自己的状态变量,应该使用普通的外部调用call,而非delegatecall。

你可以调用Counter合约的getTokenName方法验证上面的逻辑:你之前的调用已经把Counter合约自己的tokenName变量改成了1,这正是delegatecall的预期行为。

解决方案

把Counter.sol中performUpkeep方法里的delegatecall替换为普通call即可,修改后的代码片段如下:

function performUpkeep(bytes calldata) external override {
    lastTimeStamp = block.timestamp;
    counter=0;
    counter = counter + 1;
    // 把delegatecall改为call
    (bool success, bytes memory returndata) = contractBAddress.call(
          abi.encodeWithSignature("setTokenName(uint256)", counter)
    );

    // 后面的校验逻辑保持不变即可
    if (success == false) {
        if (returndata.length > 0) {
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert("Function call reverted");
        }
    }
}

修改后重新部署即可正常修改ContractB的tokenName状态变量,直接调用ContractB的getTokenName就能看到更新后的值。

内容的提问来源于stack exchange,提问作者Irwing Tello

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 04:36:04