前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Uniswap Permit2 - 高效、一致和安全的授权

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

作者头像
Tiny熊
发布2023-01-09 17:46:58
1.5K0
发布2023-01-09 17:46:58
举报

本文作者:翻译小组[1]

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

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

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

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

典型授权模式

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

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

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

  • 糟糕的用户体验, 用户必须对他们打算使用的每个代币授权给每个新的协议,这导致了混乱的用户体验,同时这几乎总是一个单独的交易,浪费了 Gas 和时间。
  • 糟糕的安全性,应用程序通常要求用户授权最大限额,以避免重复上述用户体验问题。这意味着,如果协议被利用,每个用户授权协议使用的代币都有可能被直接从他们的钱包里拿走(因为应用程序可以无限期地访问钱包的整个代币余额)。

授权签名(EIP-2612)模型

EIP-2612[6] 对代币的授权进行了迭代。用户可以通过在他们的交易中附加一个授权签名(Permit)信息来与应用合约交互,而不需要事先授权。

让我们看看 ERC20 的 EIP-2612 扩展所启用的方法,它通常是这样的:

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

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

  • 用户永远不需要提交一个单独的approve()交易。
  • 不再有悬空授权的必要之恶,因为许可消息授予的是即时授权,通常会立即花费。因此也可以选择一个更合理的授权额度,更重要的是,在签名授权消息可以被使用代币的时间上有一个到期时间。

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

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

Permit2 模式

最后,让我们深入探讨 Permit2 的方法,Permit2[8] 结合了这两种模式,将 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[9]标准(社区有一些相关文章[10]),使用这里[11]和这里[12]定义的 Permit2 域和类型散列。请注意,EIP-712 Permit2 对象的 spender字段需要被设置为将要消费它的合约地址。

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

代码语言:javascript
复制
    function permitTransferFrom(
        PermitTransferFrom calldata permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

这个函数的参数是:

  • permit - permit2 消息的详情, 有下面的信息。
    • token - 要转账的代币的地址。
    • amount - 此签名信息可转移的最大金额。
    • permitted 一个TokenPermissions结构,有以下字段:
    • nonce - 一个独特的数字,用来防止重用签名许可。一旦签名许可被使用,任何使用该 nonce 的其他签名许可将无效。
    • deadline - 该签名许可有效的截止时间。
  • transferDetails - 一个包含转账接收人和转账金额的结构,可以小于用户签名的金额。
  • owner - 签署许可的人,也是持有代币。通常,在简单的使用场景中,调用者和用户是同一个人,这应该被设置为调用者(msg.sender)。但在更奇特的集成中,你可能需要更复杂的检查[13]
  • signature - permit2 信息对应的 EIP-712 签名,由owner签名。如果从签名验证中还原的地址与 owner不一致,调用将失败。

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

高级集成

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

  • 自定义见证数据[15] - 你可以将自定义数据附加到 permit2 的信息中,这意味着 Permit2 的签名验证也将扩展到验证这些数据。
  • 批量转账[16] - 一个用于执行多个转账的批量 permit2 消息,由一个签名来保证。
  • Smart Nonces[17] - 在底层,nonces 实际上被写成存储槽中的位字段,并以上面的 248 位为索引。你可以通过仔细选择重用存储槽的 nonce 值来节省大量的 Gas。
  • 回调签名[18] - Permit2 支持EIP-1271[19]回调签名,它允许智能合约也签署 permit2 消息。
  • Permit2 Allowances[20] - 对于需要更多灵活性的协议,Permit2 支持一个更传统的授权模型,得到了过期时间的额外好处。

The Demo

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

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

参考资源

  • Permit2 公告[23] - Permit2 的地址也可以在这里找到
  • Permit2 Repo[24] - Permit2 智能合约代码
  • Permit2 `SignatureTransfer` 文档[25] - 由 Uniswap 提供的 Permit2 官方文档
  • Permit2 解释[26]

参考资料

[1]

翻译小组: https://learnblockchain.cn/people/412

[2]

Permit2 : https://github.com/Uniswap/permit2

[3]

Universal Router: https://github.com/Uniswap/universal-router

[4]

Permit2: https://github.com/Uniswap/permit2

[5]

EIP-20: https://eips.ethereum.org/EIPS/eip-20

[6]

EIP-2612: https://eips.ethereum.org/EIPS/eip-2612

[7]

参考这里: https://learnblockchain.cn/tags/EIP2612

[8]

Permit2: https://github.com/Uniswap/permit2

[9]

EIP-712: https://eips.ethereum.org/EIPS/eip-712

[10]

相关文章: https://learnblockchain.cn/tags/EIP712

[11]

这里: https://github.com/Uniswap/permit2/blob/main/src/EIP712.sol

[12]

这里: https://github.com/Uniswap/permit2/blob/main/src/libraries/PermitHash.sol

[13]

你可能需要更复杂的检查: https://docs.uniswap.org/contracts/permit2/reference/signature-transfer#security-considerations

[14]

签名信息 EIP-712 typehash 定义: https://github.com/Uniswap/permit2/blob/main/src/libraries/PermitHash.sol#L21

[15]

自定义见证数据: https://docs.uniswap.org/contracts/permit2/reference/signature-transfer#single-permitwitnesstransferfrom

[16]

批量转账: https://docs.uniswap.org/contracts/permit2/reference/signature-transfer#batched-permittransferfrom

[17]

Smart Nonces: https://docs.uniswap.org/contracts/permit2/reference/signature-transfer#nonce-schema

[18]

回调签名: https://github.com/Uniswap/permit2/blob/main/src/libraries/SignatureVerification.sol#L43

[19]

EIP-1271: https://eips.ethereum.org/EIPS/eip-1271

[20]

Permit2 Allowances: https://docs.uniswap.org/contracts/permit2/reference/allowance-transfer

[21]

示例代码: https://github.com/dragonfly-xyz/useful-solidity-patterns/blob/main/patterns/permit2/Permit2Vault.sol

[22]

Test用例: https://github.com/dragonfly-xyz/useful-solidity-patterns/blob/main/test/Permit2Vault.t.sol

[23]

Permit2公告: https://uniswap.org/blog/permit2-and-universal-router

[24]

Permit2 Repo: https://github.com/Uniswap/permit2

[25]

Permit2 SignatureTransfer 文档: https://docs.uniswap.org/contracts/permit2/reference/signature-transfer

[26]

Permit2 解释: https://github.com/dragonfly-xyz/useful-solidity-patterns/tree/main/patterns/permit2

Twitter : https://twitter.com/NUpchain Discord : https://discord.gg/pZxy3CU8mh

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 典型授权模式
  • 授权签名(EIP-2612)模型
  • Permit2 模式
  • 集成 Permit2
  • 高级集成
  • The Demo
  • 参考资源
    • 参考资料
    相关产品与服务
    区块链
    云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档