ERC-7884: 操作路由器
一种允许智能合约将写操作重定向到外部系统的协议。
Authors | Lucas Picollo (@pikonha), Alex Netto (@alextnetto), Nick Johnson (@arachnid) |
---|---|
Created | 2025-01-23 |
Discussion Link | https://ethereum-magicians.org/t/operation-router/22633 |
摘要
本 EIP 介绍了一种允许智能合约将写操作重定向到外部系统的协议。该协议定义了一种标准化方式,使合约能够指示操作应由部署到 L2 链、L1 或链下数据库的合约处理,从而为简单的开发者体验和客户端实现提供了一个入口点。
动机
随着以太坊生态系统的发展,越来越需要有效的方式来管理跨不同层和系统的数据存储。
该协议通过以下方式应对这些挑战:
- 提供一种通过 view 函数确定操作处理程序的 gas 有效方式
- 实现与 L2 解决方案和链下数据库的无缝集成
- 通过类型化签名和标准化接口维护强大的安全保证
规范
核心组件
该协议由三个主要组件组成:
- 一个名为
getOperationHandler
的 view 函数接口,用于确定操作处理程序,该处理程序可以是以下类型之一: a. 用于链上处理程序的OperationHandledOnchain
b. 用于通过网关的链下处理程序的OperationHandledOffchain
- 用于链下存储授权的标准化消息格式
接口
interface OperationRouter {
/**
* @dev 当在 getOperationHandler 函数上收到不支持的编码函数时引发的错误
*/
error FunctionNotSupported();
/**
* @dev 当变更正在链上(即 Layer 1 或 Layer 2)被延迟时引发的错误
* @param chainId 要执行延迟变更的链 ID。
* @param contractAddress 应该与延迟变更进行交易的合约地址。
*/
error OperationHandledOnchain(
uint256 chainId,
address contractAddress
);
/**
* @notice 用于定义 EIP-712 中定义的类型化数据签名的域的结构体。
* @param name 签名对应的合约的用户友好名称。
* @param version 正在使用的域对象的版本。
* @param chainId 签名对应的链的 ID
* @param verifyingContract 签名相关的合约地址。
*/
struct DomainData {
string name;
string version;
uint64 chainId;
address verifyingContract;
}
/**
* @notice 用于定义链下存储授权的消息上下文的结构体
* @param data 原始的 ABI 编码函数调用
* @param sender 执行变更的用户的地址 (msg.sender)。
* @param expirationTimestamp 变更将过期的的时间戳。
*/
struct MessageData {
bytes data;
address sender;
uint256 expirationTimestamp;
}
/**
* @dev 当变更正在被延迟到链下实体时引发的错误
* @param sender EIP-712 域定义
* @param url 用于请求执行链下变更的 URL
* @param data 原始的 ABI 编码函数调用以及授权上下文
*/
error OperationHandledOffchain(
DomainData sender,
string url,
MessageData data
);
/**
* @notice 确定编码函数调用的适当处理程序
* @param encodedFunction ABI 编码函数调用
*/
function getOperationHandler(bytes calldata encodedFunction) external view;
}
链上流程指定如下:
重要的是要注意,getOperationHandler
依赖于给定的参数(编码函数)来指定请求将被重定向到哪个合约,因此,它无法处理可能导致不同目标合约的 multicall
交易。这意味着已知的 multicall
将被重定向到不同的合约,应该以顺序方式处理,首先调用 getOperationHandler
,然后向返回的合约进行实际交易。
数据库流程
到网关的 HTTP 请求遵循 EIP-3668 提出的相同标准,其中 URL 接收 /{sender}/{data}.json
,使 API 的行为就像智能合约一样。但是,引入了 EIP-712 Typed Signature 以启用身份验证。
实现示例
部署到 L1 的合约必须实现 getOperationHandler
以充当将请求重定向到相应处理程序的路由器。
contract OperationRouterExample {
function getOperationHandler(bytes calldata encodedFunction) external view {
bytes4 selector = bytes4(encodedFunction[:4]);
if (selector == bytes4(keccak256("setText(bytes32, string)"))) {
revert OperationHandledOffchain(
DomainData(
"IdentityResolver",
"1",
1,
address(this)
),
"https://api.example.com/profile",
MessageData(
encodedFunction,
msg.sender,
block.timestamp + 1 hours
)
);
}
if (selector == bytes4(keccak256("setAddress(bytes32,address)"))) {
revert OperationHandledOnchain(
10,
address(0x123...789)
);
}
}
}
客户端实现如下所示:
try {
const calldata = {
functionName: 'setText',
abi,
args: [key, value],
address,
account
}
await client.readContract({
functionName: 'getOperationHandler',
abi,
args: [encodeFunctionData(calldata)],
})
} catch (err) {
const data = getRevertErrorData(err)
switch (data?.errorName) {
case 'OperationHandledOffchain': {
const [domain, url, message] = errorResult.args as [
DomainData,
string,
MessageData,
]
await handleDBStorage({ domain, url, message, signer })
}
case 'OperationHandledOnchain': {
const [chainId, contractAddress] = data.args as [bigint, `0x${string}`]
const l2Client = createPublicClient({
chain: getChain(Number(chainId)),
transport: http(),
}).extend(walletActions)
const { request } = await l2Client.simulateContract({
...calldata,
address: contractAddress,
})
await l2Client.writeContract(request)
}
default:
console.error('error registering domain: ', { err })
}
理由
该标准旨在启用链下写入操作,旨在作为 CCIP-Read (ERC-3668) 的补充,该标准已被社区广泛采用。
向后兼容性
本 EIP 完全向后兼容,因为它:
- 引入了与现有接口不冲突的新接口
- 使用 view 函数来收集链下信息
- 可以与现有的存储模式一起实施
安全注意事项
处理程序验证
链下处理程序必须:
- 验证 EIP-712 签名
- 实施适当的访问控制
- 安全地处理并发修改
一般建议
- 为链下处理程序实施速率限制
- 对链下通信使用安全传输 (HTTPS)
- 监控可能表明攻击的异常模式
- 为失败的事务实施适当的错误处理
版权
版权和相关权利已通过 CC0 放弃。
Citation
Please cite this document as:
Lucas Picollo (@pikonha), Alex Netto (@alextnetto), Nick Johnson (@arachnid), "ERC-7884: 操作路由器 [DRAFT]," Ethereum Improvement Proposals, no. 7884, January 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7884.