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

如何防止外部Upkeep调用合约的checkUpkeep函数避免状态篡改

核心原则:让checkUpkeep保持只读

Chainlink Automation的checkUpkeep设计初衷是仅用于状态检查,本身不应该包含任何修改合约状态的逻辑。如果你的函数里有写操作,这是违反最佳实践的,也是外部调用能修改状态的根源。

正确的做法是给checkUpkeep添加view修饰符,确保它只能读取状态:

function checkUpkeep(bytes calldata) external view returns (bool upkeepNeeded, bytes memory performData) {
    // 仅读取状态判断是否需要执行Upkeep
    upkeepNeeded = (currentBalance > threshold && block.timestamp > nextExecutionTime);
    // 传递给performUpkeep的参数(可选)
    performData = abi.encode(currentBalance);
}

强制校验调用者(仅在特殊场景下使用)

如果因为业务需求,必须在checkUpkeep中执行非只读操作(不推荐),可以通过校验调用者地址来限制只有Chainlink Automation合约能调用。不同链上的Chainlink Automation注册合约地址是固定的,你可以硬编码或通过构造函数传入:

// 以以太坊主网为例,Chainlink Automation Registry地址:0x02777053d6764996e594c3E88AF1D58D5363a2e6
address public immutable chainlinkAutomationRegistry;

constructor(address _registry) {
    chainlinkAutomationRegistry = _registry;
}

function checkUpkeep(bytes calldata) external returns (bool upkeepNeeded, bytes memory performData) {
    // 校验调用者权限
    require(msg.sender == chainlinkAutomationRegistry, "Only Chainlink Automation allowed");
    
    // 你的业务逻辑(尽量避免状态修改)
    upkeepNeeded = true;
    performData = "";
}

关于Flexible Upkeeps的额外防护

在Chainlink控制台创建Flexible Upkeep时,你可以配置Upkeep的触发条件和权限,但这只是平台层的限制。合约层的防护才是最可靠的,因为任何人都能直接调用合约的公开函数。

关键提醒

状态修改逻辑应该放在performUpkeep函数中,Chainlink Automation节点在调用performUpkeep前会自动校验权限,外部地址无法随意触发该函数执行状态修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:45:12