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

Sepolia网络Chainlink Functions调用异常:成本估算与秘钥问题

异常1:成本估算远高于实际消耗导致调用失败

  • 现象:调用subscriptionManager.estimateFunctionsRequestCost得到的估算值(如21.9 LINK)、仪表盘显示值(24.41 LINK)远高于实际最终消耗(1.18 LINK),当估算值超过可用资金时,调用直接失败。
  • 原因:
    • 估算逻辑基于当前gas价格和固定的最大回调gas限制(300000)计算上限值,实际执行时回调消耗的gas远低于该上限,导致实际成本更低。
    • Sepolia测试网gas价格波动大,估算时取的是当前gas价格峰值,实际执行时gas价格回落。
  • 修复建议:
    • 不要直接用估算值作为资金判断依据,可预留合理缓冲(比如乘以0.5的安全系数),避免过度估算导致调用失败。
    • 替换getGasPrice()为ethers.provider.getFeeData(),获取包含maxFeePerGas和maxPriorityFeePerGas的精准gas费用数据,让估算更贴近实际。

异常2:failed to fetch DONHosted secrets: not found错误

  • 现象:无论成本估算是否合理,部分调用都会抛出该秘钥获取失败错误,怀疑与多次初始化SecretsManager/SubscriptionManager、固定使用slotId=0有关。
  • 原因:
    1. 重复调用初始化方法会重置内部状态,导致秘钥上传的上下文丢失。
    2. 固定使用slotId=0易引发冲突——同一DON内的旧秘钥未过期时,会覆盖或干扰新秘钥,导致节点无法找到对应版本的秘钥。
    3. 秘钥上传后未等待同步到所有DON节点就发起请求,部分节点未同步到秘钥就执行请求。
  • 修复建议:
    • 避免重复初始化:将subscriptionManager.initialize()和secretsManager.initialize()移到应用初始化阶段,仅执行一次,不要每次请求都调用。
    • 动态分配slotId:用时间戳后几位或递增数字作为slotId,避免固定值引发的冲突。
    • 增加同步延迟:在uploadEncryptedSecretsToDON后添加1-2秒延迟,确保秘钥同步到所有节点后再发起链上请求。
    • 验证上传结果:遍历网关URL单独确认秘钥上传状态,确保所有网关都成功接收后再继续。

代码调整示例

前端代码优化(避免重复初始化+动态slotId)

// 应用初始化阶段执行,仅调用一次
let subscriptionManagerReady = false;
let secretsManagerReady = false;

async function initManagers() {
  if (!subscriptionManagerReady) {
    await subscriptionManager.initialize();
    subscriptionManagerReady = true;
  }
  if (!secretsManagerReady) {
    await secretsManager.initialize();
    secretsManagerReady = true;
  }
}

// 请求流程内
await initManagers();
const gasFeeData = await signer.getFeeData();
const gasPriceWei = gasFeeData.maxFeePerGas.toBigInt();

// 动态生成slotId
const slotIdNumber = Math.floor(Date.now() / 1000) % 1000; 

const encryptedSecretsObj = await secretsManager.encryptSecrets(secrets);
const uploadResult = await secretsManager.uploadEncryptedSecretsToDON({
  encryptedSecretsHexstring: encryptedSecretsObj.encryptedSecrets,
  gatewayUrls: gatewayUrls,
  slotId: slotIdNumber,
  minutesUntilExpiration: expirationTimeMinutes,
});

// 等待秘钥同步
await new Promise(resolve => setTimeout(resolve, 2000));

链上代码增加验证逻辑

FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source);
// 确保slotId和版本号有效再添加秘钥
if (donHostedSecretsVersion > 0 && donHostedSecretsSlotID != 0) {
    req.addDONHostedSecrets(
        donHostedSecretsSlotID,
        donHostedSecretsVersion
    );
}
if (args.length > 0) req.setArgs(args);
requestId = _sendRequest(
    req.encodeCBOR(),
    subscriptionId,
    gasLimit,
    donID
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:33:17