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

如何确保performUpkeep执行完成前不会被重复触发调用?

你可以通过添加请求状态锁的方式解决这个问题,同时不会影响原有的失败重试逻辑,具体实现步骤如下:

  • 新增一个布尔类型的状态变量,用来标记当前是否存在正在等待链下数据返回的请求
  • 在checkUpkeep的判断逻辑中新增状态锁校验,只有没有待处理请求时才允许返回upkeepNeeded=true
  • 进入performUpkeep后第一时间修改状态锁标记,避免等待链下返回的窗口期被重复触发
  • 链下数据回调时无论请求成功还是失败都释放状态锁,失败场景下因为没有更新latestDateChecked,后续checkUpkeep会自动重新返回true触发重试

修改后的代码示例:

// 新增状态锁变量,默认值为false
bool public isRequestPending;

function checkUpkeep(bytes calldata checkData)
  external
  view
  returns (bool upkeepNeeded, bytes memory performData)
{
  require(revealed);
  require(round < 7);
  uint32 secondsInDay = 86_400;
  // 新增状态锁判断,只有无待处理请求才满足触发条件
  upkeepNeeded = !isRequestPending && _getDateBeforeTimestamp(block.timestamp) >= latestDateChecked + secondsInDay;
  performData = checkData;
}

function performUpkeep(bytes calldata /* performData */) external {
  // 执行请求前先上锁,避免重复触发
  isRequestPending = true;
  requestVolumeData(); 
}

// 原有的链下数据回调函数
function fulfillVolumeData(uint256 volume, bool requestSuccess) external onlyOracle {
  // 无论请求成功失败都先释放锁
  isRequestPending = false;
  if(requestSuccess) {
    // 仅请求成功时更新日期
    latestDateChecked = _getDateBeforeTimestamp(block.timestamp);
    // 其余业务逻辑
  }
  // 请求失败时不更新latestDateChecked,后续checkUpkeep会自动触发重试
}

注意需要给fulfill回调函数添加权限控制,仅允许你对接的预言机节点调用,避免恶意用户手动解锁状态锁导致异常重复执行。

内容的提问来源于stack exchange,提问作者Alexa S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 21:36:03