Universal Executor Accounts (UEA) 是 Push Chain 上的一种确定性智能合约账户,用于代表外部链用户与 Push 应用交互,无需用户拥有 Push 原生钱包。
src/uea/UEA_EVM.solsrc/uea/UEA_SVM.solsrc/uea/UEAFactory.solsrc/uea/UEAProxy.solsrc/uea/UEAMigration.solsrc/interfaces/IUEA.solsrc/interfaces/IUEAFactory.sol通用执行账户(Universal Executor Account,简称 UEA)是一个部署在 Push Chain 上的确定性智能合约账户,它代表来自外部链的用户,并允许该用户在无需“原生在 Push 上”的情况下与 Push 应用交互。UEA 并非要求用户创建 Push 原生钱包/账户,而是将每个外部身份映射到一个 UEA,并将该 UEA 视为用户在 Push 执行环境中的链上身份。
目前有两种 UEA 实现:
ecrecover)验证所有权。0x00000000000000000000000000000000000000ca 的验证器预编译进行验证)验证所有权。在两种情况下,UEA 都成为 Push 上的实际调用者:当执行有效载荷时,应用会看到 msg.sender == UEA,从而为用户在 Push 上提供一个稳定的身份,该身份与其外部链密钥绑定。
示例:Bob 是一名以太坊用户,想要存入资金并执行一次 Push 链调用。
Bob 在以太坊上提交入向请求
以太坊侧网关锁定/托管资金并发出事件
验证者/中继器观察该事件并最终将其提交至 Push
Push 将包装后的表示(pTokens)铸造到 Bob 的 UEA
Push 确保 Bob 的 UEA 存在
UEAFactory.deployUEA(UniversalAccountId) 确定性地部署他的 UEA。Push 通过 Bob 的 UEA 执行入向有效载荷
UEA.executeUniversalTx(payload, signature)。如果调用者是 UNIVERSAL_EXECUTOR_MODULE(地址 0x14191Ea54B4c176fCf86f51b0FAc7CB1E71Df7d7),则跳过签名验证。否则,UEA 在执行前验证签名。目标 Push 合约被调用,就像 Bob 是执行者一样——即目标合约看到 msg.sender == Bob 的 UEA。目标合约运行并在 Bob 的 UEA 身份下更新状态
以太坊(外部链) Push Chain
────────────────────────── ─────────────────────────
Bob(EOA / 智能账户)
|
| 1) 将资金 + 有效载荷存入 UniversalGateway (ETH)
v
UniversalGateway (ETH)
|
| 2) 锁定/托管资金 + 发出事件(代币、金额、有效载荷、原始身份)
v
验证者 / 中继器(链下)
|
| 3) 验证事件并向 Push 提交入向执行
v
Push 入向管道
|
| 4) 如果需要,部署 UEA(通过 UEAFactory)
| 5) 将 pTokens 铸造到 Bob 的 UEA
| 6) 调用 UEA.executeUniversalTx(...)
v
Bob 的 UEA(Push Chain)
|
| 7) 在 Push 上执行目标合约调用
v
目标应用合约(Push)
|
| msg.sender == Bob 的 UEA
v
更新状态 / 执行操作
UEA 通过 UEAFactory 使用确定性部署创建,使得用户的 UEA 地址可预测且稳定。工厂从用户的 UniversalAccountId(链命名空间 + 链 ID + 所有者密钥)推导出一个盐值,并使用 OpenZeppelin 的 Clones.cloneDeterministic 在确定性地址上部署每个用户专用的 UEAProxy。然后初始化代理,使其指向正确的实现:
部署流程:
UEAFactory 使用 cloneDeterministic(salt) 克隆 UEAProxy 模板,其中 salt = keccak256(abi.encode(_id.chainNamespace, _id.chainId, _id.owner))。UEAFactory 调用 UEAProxy.initializeUEA(UEA_IMPLEMENTATION),根据链的 VM 类型设置实现。UEAFactory 通过代理调用 UEA.initialize(UniversalAccountId, factory)。这保证:一个外部身份 ↔ 一个稳定的 UEA 在 Push 上。
UEA 由外部用户的密钥控制:
domainSeparator() 和 getUniversalPayloadHash(payload) 生成)。签名通过 ECDSA.recover() 恢复,并与 address(bytes20(universalAccountId.owner)) 进行比较。VERIFIER_PRECOMPILE 的验证器预编译验证 Ed25519 签名。如果签名无效,调用会回滚。这确保第三方无法通过他人的 UEA 执行任意操作。
此外,一个受信任的系统组件(UNIVERSAL_EXECUTOR_MODULE,地址为 0x14191Ea54B4c176fCf86f51b0FAc7CB1E71Df7d7)被允许在无需签名验证的情况下调用 executeUniversalTx,因为入向执行管道已在协议层通过了身份验证。
有效载荷执行模式:
MULTICALL_SELECTOR 前缀标识)MIGRATION_SELECTOR 前缀标识,不能作为多重调用中的子调用)UEA_EVM 和 UEA_SVM 都使用共享的 _handleExecution 调度器,它读取 payload.data 的前 4 个字节以确定要使用的执行模式:
MULTICALL_SELECTOR(bytes4(keccak256("UEA_MULTICALL")))→ _handleMulticall:解码一个 Multicall[] 数组,并依次遍历每个 {to, value, data} 条目,按顺序调用每个目标。迁移不能作为多重调用中的子调用包含在内。MIGRATION_SELECTOR(bytes4(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 的单次调用)
调用迁移合约)
ueaFactory.UEA_MIGRATION_CONTRACT()(工厂管理员可变)— 迁移目标;工厂管理员控制哪个迁移合约处于活动状态0x00000000000000000000000000000000000000ca 的 Ed25519 预编译 — Push Chain 特有的 Cosmos EVM 预编译,用于 Ed25519 签名验证。硬编码;在非 Push 分叉上不可用时无备用方案。ueaFactory.UEA_MIGRATION_CONTRACT()(工厂管理员可变)— 迁移目标UEA 使用代理模式(UEAProxy),代理将执行委托给存储在固定存储槽(UEA_LOGIC_SLOT)中的 UEA 实现。迁移通过更新此实现指针到新版本来完成。
高层流程:
UEA_EVM v2 / UEA_SVM v2)。UEAMigration 合约,配置 EVM 和 SVM 的新实现地址。UEAFactory.setUEAMigrationContract(migrationAddress) 将工厂更新为指向最新的迁移合约。MIGRATION_SELECTOR 开头,且 payload.to == address(this)。这是一个专用的执行模式,而非普通调用。delegatecall 委托给迁移合约,迁移合约更新代理的实现槽(UEA_LOGIC_SLOT)为新的逻辑合约。对于 EVM UEA,调用 UEAMigration.migrateUEAEVM();对于 SVM UEA,调用 UEAMigration.migrateUEASVM()。结果:UEA 保持相同地址(身份),但运行新的逻辑。
有关完整的分步流程及图表,请参见 docs/CEA_UEA_MIGRATION_FLOW.md。
- 原文链接: github.com/pushchain/pus...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
作者暂未设置收款二维码