通用执行者账户(UEA)

pushchain 发布于 2026-03-16 阅读 93

Universal Executor Accounts (UEA) 是 Push Chain 上的确定性智能合约账户,代表外部链用户,使其无需原生注册即可与 Push 应用交互。

合约地址


什么是 UEA?

通用执行器账户(Universal Executor Account,简称 UEA)是在 Push Chain 上部署的确定性智能合约账户,代表来自外部链的用户,使用户无需“原生接入 Push”即可与 Push 应用交互。Push 不要求用户创建 Push 原生钱包/账户,而是将每个外部身份映射到一个 UEA,并将该 UEA 视为用户在 Push 执行环境中的链上身份。

目前有两种 UEA 实现:

  • UEA_EVM:适用于基于 EVM 的链(例如以太坊)。所有权通过 ECDSA 签名进行验证(采用 EIP-712 风格的负载哈希 + ecrecover)。
  • UEA_SVM:适用于基于 Solana/SVM 的链。所有权通过 Ed25519 签名进行验证(通过地址为 0x00000000000000000000000000000000000000ca 的验证器预编译进行验证)。

在这两种情况下,UEA 成为 Push 上的有效调用者:当执行负载时,应用会看到 msg.sender == UEA,从而为用户在 Push 上提供一个与其外部链密钥绑定的稳定身份。


使用 UEA 的入站流程(以太坊 → Push Chain)

示例:Bob 是以太坊用户,想要存入资金并在 Push Chain 上执行调用。

  1. Bob 在以太坊上提交入站请求

    • Bob 与以太坊侧的通用网关(Universal Gateway)交互,发送资金及编码后的负载(目标地址 + calldata),该负载目的链为 Push Chain。
  2. 以太坊侧网关锁定/托管资金并发送事件

    • 网关锁定资产,并发送一个包含代币、金额、目标详情以及编码后的调用意图的事件。
  3. 验证者/中继者观察该事件并在 Push 上完成处理

    • Push 的链下验证层(通用验证者 / 中继者 / TSS,具体取决于路线)确认事件,并准备在 Push 上执行入站操作。
  4. Push 将包装后的表示(pToken)铸造到 Bob 的 UEA

    • 在 Push Chain 上,入站流水线将相应的 pToken(例如 DAI → pDAI)铸造到 Bob 的 UEA。
  5. Push 确保 Bob 的 UEA 存在

    • 如果 Bob 是首次使用,Push 会通过 UEAFactory.deployUEA(UniversalAccountId) 确定性部署他的 UEA。
  6. Push 通过 Bob 的 UEA 执行入站负载

    • 入站流水线调用 UEA.executeUniversalTx(payload, signature)。如果调用者是 UNIVERSAL_EXECUTOR_MODULE(地址 0x14191Ea54B4c176fCf86f51b0FAc7CB1E71Df7d7),则跳过签名验证。否则,UEA 在执行前验证签名。目标 Push 合约被调用时,就好像 Bob 是执行者——即目标看到 msg.sender == Bob 的 UEA
  7. 目标合约运行并在 Bob 的 UEA 身份下更新状态

    • 任何余额、仓位、状态(质押、借贷、交换等)都根据 UEA 作为 Bob 在 Push 上的身份进行跟踪。
以太坊(外部链)                           Push Chain
──────────────────────────                         ─────────────────────────
Bob (EOA / 智能账户)
   |
   | 1) 存入资金 + 负载到 UniversalGateway (ETH)
   v
UniversalGateway (ETH)
   |
   | 2) 锁定/托管资金 + 发送事件(代币、金额、负载、来源身份)
   v
验证者 / 中继者(链下)
   |
   | 3) 验证事件并向 Push 提交入站执行
   v
Push 入站流水线
   |
   | 4) 如有需要,部署 UEA(通过 UEAFactory)
   | 5) 将 pToken 铸造到 Bob 的 UEA
   | 6) 调用 UEA.executeUniversalTx(...)
   v
Bob 的 UEA (Push Chain)
   |
   | 7) 在 Push 上执行目标合约调用
   v
目标应用合约 (Push)
   |
   | msg.sender == Bob 的 UEA
   v
状态更新 / 操作执行

UEA 的确定性创建

UEA 通过 UEAFactory 使用确定性部署创建,这样用户的 UEA 地址是可预测且稳定的。工厂根据用户的 UniversalAccountId(链命名空间 + 链 ID + 所有者密钥)生成盐值,并使用 OpenZeppelin 的 Clones.cloneDeterministic 在每个用户的 UEAProxy 的确定地址上部署代理。然后对该代理进行初始化,使其指向正确的实现:

  • UEA_EVM 用于 EVM 来源的用户
  • UEA_SVM 用于 Solana 来源的用户

部署流程:

  1. UEAFactory 使用 cloneDeterministic(salt) 克隆 UEAProxy 模板,其中 salt = keccak256(abi.encode(_id.chainNamespace, _id.chainId, _id.owner))
  2. UEAFactory 调用 UEAProxy.initializeUEA(UEA_IMPLEMENTATION),根据链的虚拟机类型设置实现。
  3. UEAFactory 通过代理调用 UEA.initialize(UniversalAccountId, factory)

这保证了一个外部身份 ↔ 一个在 Push 上稳定的 UEA。


控制模型:只有所有者才能通过 UEA 执行

UEA 由外部用户的密钥控制:

  • 对于 UEA_EVM:UEA 验证基于 EIP-712 风格的负载哈希的 ECDSA 签名,该哈希由执行请求通过 domainSeparator()getUniversalPayloadHash(payload) 生成。签名使用 ECDSA.recover() 恢复,并与 address(bytes20(universalAccountId.owner)) 进行比较。
  • 对于 UEA_SVM:UEA 通过地址为 VERIFIER_PRECOMPILE 的验证器预编译验证 Ed25519 签名。

如果签名无效,调用将回滚。这确保没有第三方可以通过他人的 UEA 执行任意操作。

此外,一个受信任的系统组件(UNIVERSAL_EXECUTOR_MODULE,地址为 0x14191Ea54B4c176fCf86f51b0FAc7CB1E71Df7d7)被允许在无需签名验证的情况下调用 executeUniversalTx,因为入站执行流水线已在协议层通过认证。

负载执行模式:

  • 单次调用:直接执行到目标合约
  • 多重调用:在一次交易中批量执行多个调用(通过 MULTICALL_SELECTOR 前缀识别)
  • 迁移:升级 UEA 实现逻辑(通过 MIGRATION_SELECTOR 前缀识别,不能作为多重调用内的子调用)

负载执行

UEA_EVMUEA_SVM 都使用共享的 _handleExecution 分发器,读取 payload.data 的前 4 个字节来确定使用哪种执行模式:

  • MULTICALL_SELECTORbytes4(keccak256("UEA_MULTICALL")))→ _handleMulticall:解码 Multicall[] 数组,并遍历每个 {to, value, data} 条目,依次调用每个目标。迁移不能作为多重调用中的子调用包含在内。
  • MIGRATION_SELECTORbytes4(keccak256("UEA_MIGRATION")))→ _handleMigration:必须是独立的负载(不能嵌套在多重调用内)。要求 payload.to == address(this)payload.value == 0。通过 delegatecall 调用 UEAFactory.UEA_MIGRATION_CONTRACT() 上的 migrateUEAEVM()(适用于 EVM UEA)或 migrateUEASVM()(适用于 SVM UEA)。
  • 其他情况_handleSingleCall:直接向 payload.to 进行 call{value}(data)
executeUniversalTx(payload, sig)
        │
        ├─ [UE 模块调用者] ──────────────────────────────────────────┐
        │                                                             │
        └─ [验证 ECDSA / Ed25519] ────────────────────────────────── │
                                                                     │
                                           _handleExecution(payload)
                                                   │
                            ┌──────────────────────┼──────────────────────┐
                            │                      │                      │
                     MULTICALL_SELECTOR   MIGRATION_SELECTOR      (其他情况)
                            │                      │                      │
                    _handleMulticall()    _handleMigration()    _handleSingleCall()
                   (批量调用)            (通过 delegatecall 调用  (单次调用到
                                          迁移合约)                 payload.to)

外部依赖

UEA_EVM

  • OZ ECDSA 库(不可变)—— EVM 密钥的签名恢复
  • ueaFactory.UEA_MIGRATION_CONTRACT()(工厂管理员可变)—— 迁移目标;工厂管理员控制哪个迁移合约处于活跃状态
  • 多重调用 / 单次调用中的目标合约 —— 不受信任,任意;UEA 不对目标行为做任何假设

UEA_SVM

  • 地址为 0x00000000000000000000000000000000000000ca 的 Ed25519 预编译 —— Push Chain 特有的 Cosmos EVM 预编译,用于 Ed25519 签名验证。硬编码;在非 Push 分叉上不可用时无后备方案。
  • ueaFactory.UEA_MIGRATION_CONTRACT()(工厂管理员可变)—— 迁移目标
  • 目标合约(不受信任,任意)

UEA 迁移概览(升级 UEA 逻辑)

UEA 使用代理模式(UEAProxy),代理将执行委托给存储在固定存储槽(UEA_LOGIC_SLOT)中的 UEA 实现。迁移通过将此实现指针更新到新版本的实现。

高级流程:

  1. 部署新的 UEA 实现(例如 UEA_EVM v2 / UEA_SVM v2)。
  2. 部署新的 UEAMigration 合约,并为 EVM 和 SVM 配置新的实现地址。
  3. 通过 UEAFactory.setUEAMigrationContract(migrationAddress) 将工厂更新为指向最新的迁移合约。
  4. 用户通过 UEA 执行路径触发迁移:负载数据必须以 MIGRATION_SELECTOR 开头,且 payload.to == address(this)。这是一种专用的执行模式,而不是普通调用。
  5. UEA 通过 delegatecall 委托给迁移合约,该合约将代理的实现槽(UEA_LOGIC_SLOT)更新为新的逻辑合约。对于 EVM UEA,调用 UEAMigration.migrateUEAEVM();对于 SVM UEA,调用 UEAMigration.migrateUEASVM()

结果:UEA 保持相同地址(身份),但运行新逻辑。

参见 docs/CEA_UEA_MIGRATION_FLOW.md 获取包含图表的完整逐步流程。

  • 原文链接: github.com/pushchain/pus...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

相关文章

0 条评论