Alert Source Discuss
⚠️ Review Standards Track: ERC

ERC-7746: 可组合安全中间件钩子

用于智能合约中可组合的运行时安全检查的接口。

Authors Tim Pechersky (@peersky)
Created 2024-07-17

摘要

本 EIP 提出一个标准接口 ILayer,用于在智能合约中实现可组合的安全层。这些层充当中间件,能够在执行前后对函数调用进行运行时验证,而无需依赖受保护合约的逻辑。这种方法有助于模块化安全,允许独立的提供商管理和升级多个合约中的安全层。

动机

当前智能合约的安全实践通常依赖于合约本身内的单体验证逻辑。这可能导致代码紧密耦合,难以隔离和解决安全问题。需要更结构化的架构,类似中间件的方法在行业中被广泛使用,允许以通用和可重复的模式,使用相同的调用签名将调用包装在其他调用中。

安全层标准引入了一种模块化方法,可以实现:

  • 独立的安全提供商: 专业的安全提供商可以专注于开发和维护特定的安全检查。
  • 可组合的安全: 可以组合多个层来创建针对单个合约需求量身定制的综合安全配置文件。
  • 可升级性: 无需更改受保护的合约即可更新安全层。
  • 灵活性: 各个层可以执行各种验证检查,包括访问控制、输入清理、输出验证等。

拥有此类层的通用标准可以帮助构建更安全和模块化的系统,并使安全提供商能够构建通用的、面向服务的安全预言机解决方案。

规范

实现 ILayer 接口的合约必须提供两个函数:

// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.20;

interface ILayer {
    /// @notice 在执行函数调用之前对其进行验证。
    /// @param configuration 特定于层的配置数据。
    /// @param selector 要调用的函数选择器。
    /// @param sender 发起调用的地址。
    /// @param value 与调用一起发送的 ETH 数量(如果有)。
    /// @param data 函数调用的 calldata。
    /// @return beforeCallResult 要传递给 `afterCallValidation` 的任意数据。
    /// @dev 如果验证失败,则必须回退。
    function beforeCall(
        bytes memory configuration,
        bytes4 selector,
        address sender,
        uint256 value,
        bytes memory data
    ) external returns (bytes memory);

    /// @notice 在执行函数调用之后对其进行验证。
    /// @param configuration 特定于层的配置数据。
    /// @param selector 要调用的函数选择器。
    /// @param sender 发起调用的地址。
    /// @param value 与调用一起发送的 ETH 数量(如果有)。
    /// @param data 函数调用的 calldata。
    /// @param beforeCallResult `beforeCallValidation` 返回的数据。
    /// @dev 如果验证失败,则必须回退。
    function afterCall(
        bytes memory configuration,
        bytes4 selector,
        address sender,
        uint256 value,
        bytes memory data,
        bytes memory beforeCallResult
    ) external;
}

受保护的合约可以通过在执行其逻辑之前调用 beforeCallValidation 函数,并在执行之后调用 afterCallValidation 函数来集成安全层。可以注册和执行多个层,并以定义的顺序进行。如果任何层回退,则受保护的合约必须回退。

理由

灵活性layerConfig 参数允许特定于层的自定义,使单个层实现能够满足具有不同要求的多个合约。

非静态调用:各个层可以维护自己的状态,从而实现更复杂的验证逻辑(例如,速率限制、使用情况跟踪)。

严格验证:验证失败时回退,可确保故障安全机制,防止执行可能有害的交易。

Gas 成本:各个层自然会产生与其执行相关的 gas 成本。但是,增强的安全性和模块化的好处大于这些成本,尤其是在区块链技术不断发展并且我们期望 gas 成本会随着时间推移而降低的情况下。

参考实现

ILayer 接口和示例受保护合约的参考实现可以在存储库中找到: 在 ILayer.sol 中,提供了参考接口。

在此测试中,Protected.sol 合约受到 RateLimitLayer.sol 层的保护。RateLimitLayer 实现了 ILayer 接口,并强制执行客户端已配置的速率限制。 Drainer 模拟了一个以恶意方式运行的易受攻击的合约。在 test.ts 中,Drainer 合约试图从 Protected 合约中耗尽资金。假设 Protected 合约存在一个漏洞,该漏洞允许部分未经授权地访问状态。 RateLimitLayer 被配置为仅允许来自同一发送者的每个区块 10 笔交易。该测试检查 Drainer 合约是否能够从 Protected 合约中耗尽资金。

安全考虑事项

层信任:在将任何安全层集成到您的合约之前,请彻底审计和审查它。恶意层会损害合约的安全性。

版权

版权及相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Tim Pechersky (@peersky), "ERC-7746: 可组合安全中间件钩子 [DRAFT]," Ethereum Improvement Proposals, no. 7746, July 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7746.