DEFI - ComposableCoW 架构
本文档介绍了 ComposableCoW 的架构设计,旨在提高 CoW Protocol 与 Safe 的互操作性,实现更高效的条件订单处理。
ComposableCoW 架构
以下原则已应用于架构设计中:
- 对于
n阶的创建/替换/删除操作,具有O(1)的效率。 - 对于 EOA(资产的自我托管,无需创建“容器”合约),条件订单应该表现得与离散订单相同。
- 订单是 加粗无状态加粗 的,任何所需的数据都通过
calldata传递。 - 使 CoW 成为
Safe的一等公民,反之亦然 ??。
假设
- CoW 协议强制执行单次使用订单,即任何
GPv2Order都不能被多次执行。
定义
加粗条件订单加粗:表示 0..n 个离散订单的逻辑结构。
加粗离散订单加粗:提交给 CoW 协议 API 的订单(即 GPv2Order.Data),即 CoW 协议定义的单个 orderUid。
为了本文档的目的,如果未指定订单的加粗类型加粗,则应假定为加粗条件订单加粗。
使用案例
目前,与 CoW 交互的加粗智能合约加粗需要:
- 调用
GPv2Settlement.setPreSignature(orderUid)(API 签名类型为“预签名”);或者 - 实现
isValidSignature(bytes32,bytes)(API 签名类型为“eip1271”),其中传递的bytes32参数是GPv2Order.Data的 EIP-712 摘要。
目前,订单一直在链上产生新的合约,需要处理基本的 retrieve / cancel 功能来恢复资产。Safe 已经为此目的提供了最好的解决方案,所以我们不要重新发明轮子!?
此修订后的架构旨在实现的使用案例包括:
- 自动将 token ABC 兑换为 XYZ,当 ABC 的余额高于定义的阈值时。
- Good after time (
GAT) 订单(离散订单,以开始时间为条件)。 - 通过将订单分解为
n x GAT订单来实现 TWAP。 - 私有条件订单(追踪止损)
- Wait4CoW 订单(仅与其他 CoW 交易者匹配订单)
- 同时执行以上所有操作(
n x conditional orders)
当前架构
架构分析是从使用
Safe与 CoW 协议的角度进行的。
所有 CoW 协议的离散订单都经过“签名”。签名方法包括:
- EIP-712 (gasless)
- Eth-Sign (gasless)
- EIP-1271 (gasless)
- Pre-Sign (tx)
EOA Only
EOA Only
Contract Only
Contract & EOA
GPv2Settlement
EIP-712
Eth-Sign
EIP-1271
Pre-Sign
通过 Safe 进行签名是通过 approvedHash 或 threshold 签名完成的,如下所示:
delegatecall SigningLib
manual assembly of signatures
Safe
approvedHash - tx
threshold - gasless
因此,当使用 Safe 时:
- 每个 离散订单(即
orderUid)必须由Safe单独批准/签名。 - 从 CoW 协议和
Safe的角度来看,只有threshold类型的 EIP-1271 签名是 gasless 的。
结果是用户体验受到了极大的限制。
ComposableCoW
该合约实现了 ISafeSignatureVerifier,旨在与 ExtensibleFallbackHandler 一起使用 - Safe 的一个新的 FallbackHandler。ExtensibleFallbackHandler 为 safe 提供了第三种 EIP-1271 验证方法 - 它允许将 EIP-712 域委托给自定义合约。
因此,ComposableCoW 将处理 GPv2Settlement.domainSeparator() EIP-712 域的所有 EIP-1271 签名。
因此,ComposableCoW 负责:
- 每个
owner的n个条件订单的离散订单验证路由。 - 从条件订单中查找离散订单(瞭望塔)。
订单数据
每个条件订单在清算时都具有以下属性/数据,具体取决于实现:
handler- 将验证条件订单参数的合约。salt- 允许同一类型和数据的多个条件订单。staticData- 条件订单创建的所有 加粗离散加粗 订单都可以使用的数据。offchainData- 从链下加粗可选地加粗 提供给 加粗离散加粗 订单的数据。
由于所有这些(不包括 offchainData)在创建时都是已知的,因此它们被组合在结构体 ConditionalOrderParams 中:
struct ConditionalOrderParams {
IConditionalOrder handler;
bytes32 salt;
bytes staticData;
}
ConditionalOrderParams 具有以下属性:
H(ConditionalOrderParams)必须 是唯一的。- 当需要时,
salt应该 设置为密码学上安全的随机值,以确保 (1)。 - 提供订单保密性(直到从此条件订单中截取的离散订单广播到 CoW 协议 API)。
- 所有值在调用订单类型的
verify之前,都由ComposableCoW验证。
offchainInput 具有以下属性:
- 允许输入(例如来自链下 oracle 的输入),这些输入在订单创建时是不已知的。
- 不 由
ComposableCoW验证。验证是 handler 的责任。
警告:订单实现必须验证 offchainInput!
存储
mapping (address => bytes32) roots; // For Merkle roots (n conditional orders)
mapping (address => mapping (bytes32 => bool)) singleOrders; // Per conditional order (if not in Merkle root)
清算执行路径
CoW 协议订单清算执行路径(假设 safe):
call: isValidSignature
delegatecall: isValidSignature
call: isValidSignature
call: isValidSafeSignature
call: verify
GPv2Settlement
SafeProxy
SafeSingleton : FallbackManager
ExtensibleFallbackHandler : SignatureVerifierMuxer
ComposableCoW
IConditionalOrder
实现 ISafeSignatureVerifier 意味着 ComposableCoW 将实现 isValidSafeSignature:
function isValidSafeSignature(
Safe safe,
address sender,
bytes32 _hash,
bytes32 domainSeparator,
bytes32, // typeHash
bytes calldata encodeData,
bytes calldata payload
) external view override returns (bytes4 magic);
encodeData:在清算期间被验证的订单的 ABI 编码的GPv2Order.Data。payload:abi.encode(bytes32[] proof, ConditionalOrderParams params, bytes offchainInput)typeHash被忽略,因为 CoW 协议只有一个typeHash(GPv2Order.Data)。
清算有效性
以下安全约束由 ComposableCoW 强制执行:
ConditionalOrderParams必须 获得owner授权才能使用。
isValidSafeSignature
valid
invalid
valid
invalid
valid
invalid
Extensible Fallback Handler: SignatureVerifierMuxer
Check Authorisation: MerkleRoot
Proof & ConditionalOrderParams
IConditionalOrder:verify
Check Authorisation: Single Order
ConditionalOrderParams
Revert
Return ERC1271 Magic
Merkle Root
叶子: H(ConditionalOrderParams),即 H(handler || salt || data)
属性:
- 实现了对于添加/删除
n个条件订单的O(1)gas 效率。
方法:
调用者将 abi.encode(bytes32[] proof, ConditionalOrderParams params) 作为 payload 参数传递,其中 proof 包含 Merkle Tree 证明。
授权:
如果 proof 断言 节点 H(params) 是 merkle tree roots[owner] 的成员,则订单 O 为有效。
单个订单
属性:
- 用于启用订单的更简单的方法(更少的工具开销)。
- Gas 昂贵(每个订单
nxSSTORE)。
方法:
调用者将 abi.encode(bytes32[] proof, ConditionalOrderParams params, bytes offchainInput) 作为 payload 参数传递,其中 proof 是零长度的 bytes32[]。
授权:
如果 singleOrders(owner, H(params)) == true,则订单 O 有效。
添加 / 删除订单
owner 使用适用的 setter 方法,具体取决于他们希望如何指定订单。
Merkle Root
owner 调用 setRoot(bytes32 root, Proof calldata proof) setter 方法。
struct Proof {
uint256 location;
bytes data;
}
root:条件订单的 Merkle Tree(叶子 =H(params))。proof:瞭望塔可能会从中找到证明的位置。
私有: Proof({location: 0, data: bytes("")}) - 没有证明可供瞭望塔使用。
日志: Proof.location = 1 并且 Proof.data = abi.encode(bytes[] order),其中 order = abi.encode(bytes32[] proof, ConditionalOrderParams params)。
当设置新的 merkle root 时,会发出 MerkleRootSet(address indexed owner, bytes32 root, Proof proof)。
注意: ComposableCoW 将不验证通过 proof 参数传递的证明数据以进行 setRoot。验证/确认这一点是客户端和瞭望塔的责任。
注意: Proof.location 有意未设置为 enum,以便将来可以集成其他证明位置,包括但不限于 Swarm、Waku、IPFS 等。
单个订单
owner 调用相应的 setter 方法:
- 创建订单:
create(ConditionalOrderParams params, bool dispatch)
如果 owner 想要公开订单,则将 dispatch 设置为 true,并且订单创建将导致发出 ConditionalOrderCreated(address indexed owner, ConditionalOrderParams params)。
- 删除订单:
remove(bytes32 orderHash)
要删除订单,请从初始的 ConditionalOrderCreated 设置 orderhash = H(params)。不发出任何事件,因为订单已失效(任何试图截取离散订单的瞭望塔都会看到 getTradeableOrder() 将 revert)。
离散订单生成
默认是为条件订单使用 Factory 基本模式,其中基于订单的属性,它能够生成可交易的订单(GPv2Order.Data)。
为此,订单实现了 IConditionalOrderFactory 接口。遵循此模式,开发人员必须确保:
H(IConditionalOrderFactory.getTradeableOrder(owner,sender,params,offchainInput)) == _hash
其中 _hash 是传递到 isValidSignature() 调用中的 _hash。
高级条件订单
这些实现了顶级的 IConditionalOrder 接口,该接口仅提供原始的 verify 方法,并且不允许生成订单。
瞭望塔
由于这些订单没有被 CoW 协议 API 自动索引,因此需要某种方法将它们转发给 CoW 以包含在批处理中。这是通过引用 ComposableCoW 发出的事件来完成的:
ConditionalOrderCreated(address indexed owner, ConditionalOrderParams params)MerkleRootSet(address index owner, bytes32 root, Proof proof)
加粗发出加粗 上述方法的合约应提供一种方法:
function getTradeableOrderWithSignature(
address owner,
bytes32[] proof,
ConditionalOrder params,
bytes offchainInput
) external view (GPv2Order.Data memory, bytes memory signature);
在 ComposableCoW 的上下文中,这将:
- 确定
owner是否是safe,并为 EIP-1271signature提交给 CoW 协议提供SignatureVerifierMuxer适当的格式。 - 如果不是
safe,则根据abi.encode(domainSeparator, staticData, offchainData)格式化 EIP-1271signature。
ComposableCoW 将:
- 检查订单是否已授权。
- 通过使用
IERC165检查订单类型是否支持离散订单生成(即IConditionalOrderFactory)(如果不支持,则revert,允许瞭望塔修剪无效的受监控条件订单)。 - 调用 handler 上的
getTradeableOrder以获取GPv2Order.Data - 如上所述生成签名数据。
注意: 取消/删除订单时无需发出这些事件,因为调用 getTradeableOrderWithSignature 将产生一个带有自定义 error 的 revert,表明该订单在当前状态下永远无效。
接口
IConditionalOrder
这是条件订单的根级别接口,实现了:
function verify(
address owner,
address sender,
bytes32 hash,
bytes32 domainSeparator,
bytes calldata staticInput,
bytes calldata offchainInput
GPv2Order.Data calldata order,
) external view;
注意: 如果指定的参数与有效订单不对应,则 verify 方法必须 revert。
IConditionalOrderFactory
通过实现 ERC165 和:
function getTradeableOrder(
address owner,
address sender,
bytes calldata staticInput,
bytes calldata offchainInput
) external view returns (GPv2Order.Data memory);
允许生成离散订单以提交给 CoW 协议。
- 原文链接: hackmd.io/pmZX_qT2Q1yw59...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~