区块链中文技术社区

Uniswap Permit2 - 高效、一致和安全的授权

Uniswap Labs发布了两个新的智能合约Permit2和UniversalRouter, Permit2 确实可以让链上交易体验上一层楼。

前几天,Uniswap Labs发布了两个新的智能合约 Permit2 和 Universal Router :

  1. Permit2 允许代币授权在不同的应用程序中共享和管理,创造一个更统一、更具成本效益、更安全的用户体验。
  2. Universal Router 将ERC20和NFT兑换统一到一个单一的兑换路由器。与Permit2整合后,用户可以在一次兑换交易中兑换多个代币和NFT,同时节省Gas费。

Uniswap最初构思Permit2和Universal Router是为了改进Uniswap自己的产品,优化Gas成本,简化用户交易流程,并加强安全性。在构思的过程中,Unswap觉得其他应用可以从整合这些合约中大大受益。Uniswap 本身致力于建设公共基础设施,因此设计了这些合约,提供整个开发者生态系统使用,包括广泛的文档、SDK。

Permit2是一个代币授权合约,可以在不同的智能合约中安全地共享和管理代币授权。随着越来越多的项目与Permit2集成,可以在所有应用程序中对代币授权进行标准化。反过来,Permit2将通过降低交易成本来改善用户体验,同时提高智能合约的安全性。

典型授权模式

以下是EIP-20中定义的典型代币授权(Approve)方法图示:

  1. Alice在一个ERC20上调用approve(),向一个合约授予支出授权。
  2. Alice在合约上调用一个交互函数,该函数又在ERC20代币合约上调用transferFrom(),转账她的代币。

显然,这种模式是可行的(它无处不在),并且最终可以相当灵活,因为协议通常会最终不间断地长期访问用户的代币。但它有两个众所周知的现实世界的问题。

授权签名(EIP-2612)模型

EIP-2612 对代币的授权进行了迭代。用户可以通过在他们的交易中附加一个授权签名(Permit)信息来与应用合约交互,而不需要事先授权。
让我们看看ERC20的EIP-2612扩展所启用的方法,它通常是这样的:

  1. Alice签署一个链外的 "permit(签名授权)" 信息,表示她希望授予一个合约一个(EIP-2612)代币的使用权。
  2. Alice提交签署的消息,作为她与所述合约交互的一部分。
  3. 合约调用代币上的 "permit()" 方法,它会使用签名授权信息和签名,同时授予合约一个授权。
  4. 合约现在有了授权,所以它可以在代币上调用transferFrom(),转账由Alice持有的代币。

这解决了典型ERC20 授权方法的两个问题:

虽然EIP-2612使代币授权更加安全,但在EIP-2612之前推出的代币并不支持签名授权功能,而且并非所有较新的代币都采用该功能,这就是悲催的现实。因此大多数时候,这种方法不可行。

关于EIP-2612, 我那个登链社区上还有一些文章探讨,可参考这里

Permit2模式

最后,让我们深入探讨Permit2的方法,Permit2 结合了这两种模式,将EIP-2612的用户体验和安全优势扩展到也涵盖了普通的ERC20代币!
为了说明Permit2的革命性,在一个常见的场景中,协议需要转账 Alice持有的代币。

  1. Alice在一个ERC20上调用approve(),典型的方式为的Permit2合约授予一个无限的授权。
  2. Alice签署一个链下 permit2 消息,该消息表明协议合约被允许代表她转账代币。
  3. Alice在协议合约上调用一个交互函数,将签署的 permit2 消息作为参数传入。
  4. 协议合约在Permit2合约上调用 permitTransferFrom(),而Permit2合约又使用其授权(在1中授予)在ERC20合约上调用 "transferFrom()",转账Alice持有的代币。

要求用户首先授予一个明确的授权交易,这似乎是一种倒退。但是,用户不是直接授予协议,而是将其授予规范的Permit2合约。这意味着,如果用户之前已经这样做了,比如说与另一个集成了Permit2的协议进行交互,那么其他每一个协议都可以跳过这个步骤。

这太棒了。

协议不会直接调用ERC20代币上的transferFrom()来执行转账,而是调用规范的Permit2合约上的permitTransferFrom()。Permit2 位于协议和ERC20代币之间,跟踪和验证permit2消息,然后最终使用其授权直接在ERC20上执行transferFrom()调用。这种间接性使得Permit2可以将类似于EIP-2612的好处扩展到每一个现有的ERC20代币上。

同时,像EIP-2612 签名授权信息一样,Permit2 信息也会过期,以限制漏洞的攻击窗口。

集成 Permit2

对于集成Permit2的前端来说,它需要获取一个用户签名,并将其传递到交易中。这些签名签署的Permit2消息结构(PermitTransferFrom)必须符合EIP-712标准(社区有一些相关文章),使用这里这里定义的Permit2域和类型散列。请注意,EIP-712 Permit2对象的 spender 字段需要被设置为将要消费它的合约地址。

智能合约的整合实际上是相当容易的! 任何需要转账用户持有的代币的函数只需要接受任何的许可信息细节和相应的EIP-712用户签名。为了实际转账代币,我们将在规范的Permit2合约上调用permitTransferFrom()。该函数的声明为:

function permitTransferFrom(
    PermitTransferFrom calldata permit,
    SignatureTransferDetails calldata transferDetails,
    address owner,
    bytes calldata signature
) external;

这个函数的参数是:

注意,PermitTransferFrom结构不包括签名信息 EIP-712 typehash 定义中的spender字段。在处理过程中,它将被填入我们的合约地址(permitTransferFrom()的直接调用者)。这就是为什么用户签署的EIP-712对象的spender字段必须是这个合约的地址。

高级集成

前面涵盖了 Permit2 提供的基本功能,但你还可以用它做更多的事情!

The Demo

这里提供的示例代码是一个简单的金库,用户可以使用Permit2将ERC20代币存入其中,随后可以提取。因为它是多用户的,它需要启动转账,以便可靠地记入哪个账户拥有哪个余额。通常情况下,这需要给金库合约授予授权,然后让金库对代币本身执行transferFrom(),但Permit2让我们跳过了这个麻烦!

Test用例部署了一个本地的、字节码的主网Permit2合约的分叉,以测试金库的一个实例。EIP-712 Hash 和签名生成也是用solidity/foundry编写的,但通常应该在链外用你选择的语言在前端或后端执行。

参考资源

转载自:https://learnblockchain.cn/article/5161

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »