ERC-4337 Web3j 智能账户教程
核心要点
- 作为参与 LF 去中心化信任指导计划下的 Web3j 库完整开发生命周期项目的一部分,我开发了 ERC-4337 智能帐户教程。
- 它演示了如何创建一个最小的 ERC-4337 兼容智能帐户,使用 Web3j 编译和部署它,并使用特定的帐户抽象用户操作与其交互,包括智能帐户之间的函数调用和 ETH 传输。
- 我们可以通过这种预充值存款机制手动为部署的账户提供 ETH 资金,以支付其运营的 Gas 成本。
- 通过支持 UserOperation 的创建和交互,Web3j 使开发人员能够尝试以太坊最具变革性的升级之一。

作为参与 LF 去中心化信任指导计划下的 Web3j 库完整开发生命周期项目的一部分,我开发了 ERC-4337 智能帐户教程。它演示了如何创建一个最小的 ERC-4337 兼容智能帐户,使用 Web3j 编译和部署它,并使用特定的帐户抽象用户操作与其交互,包括智能帐户之间的函数调用和 ETH 传输。
简介:什么是帐户抽象?
账户抽象(AA)是以太坊的一项改进,重新定义了用户账户在链上的工作方式。传统上,以太坊区分两种类型的账户:
外部拥有账户 (EOA),由私钥控制(例如 MetaMask 钱包)。
,由私钥控制(例如 MetaMask 钱包)。合约账户,由智能合约代码控制。
账户抽象允许智能合约充当用户账户,从而模糊了这条界限。这些智能账户可以发起交易、灵活支付汽油费(例如,通过付款员),并支持自定义身份验证逻辑(例如生物识别、多重签名或社交恢复),所有这些都在代码中定义。
AA 背后的关键概念是通过标准化接口 (IAccount) 将交易验证和执行逻辑委托给智能合约,并通过 EntryPoint 合约进行中继机制。用户不是直接发送交易,而是提交 UserOperations,捆绑器将其中继到 EntryPoint。然后,EntryPoint 调用智能帐户的 validateUserOp() 和execute() 方法来授权和执行操作。
要了解有关帐户抽象基础知识的更多信息,您可以查看此博客文章:https://blog.web3labs.com/account-abstraction-in-ethereum-part-1/
第 1 部分:合同创建
首先克隆 eth-infinitism 帐户抽象存储库:
对于简单的设置,我们只需复制这两个文件即可:
合约/接口/IAccount.sol
合约/接口/PackedUserOperation.sol
复制文件可以避免管理整个存储库。在本例中,我将它们放在名为 SolidityFiles 的文件夹中。
然后,我们通过粘贴以下最小合约在同一目录中创建一个名为 SmartAccount.sol 的新 Solidity 文件:
我们来看看这个合约做了什么:
validateUserOp() — 在操作验证期间由 EntryPoint 调用。它验证该操作是否已获得授权,并在必要时向 EntryPoint 发送预付款以支付 Gas 费用。该预付款将在执行后退还。 (对于本教程,请注意,我们的 validateUserOp() 始终返回 0,绕过签名检查。这不应该在生产环境中完成。)
在生产环境中完成。)execute() — 允许 EntryPoint 指示智能帐户发送 ETH 或向任何目的地进行合约调用。这就是账户在验证后实际在链上执行操作的方式。
receive()——直接接受 ETH。
第 2 部分:使用 Web3j 部署智能帐户
合同包装器准备就绪后,就可以部署我们的智能帐户了。
让我们首先使用 Web3j-CLI 创建一个新的 Web3j 项目,使用命令
该命令将使用我们刚刚编码的合约创建一个新项目。
(要了解更多信息,请查看 Web3j 文档:https://docs.web3j.io/4.14.0/command_line_tools/#import-an-existing-project)
然后,在我们的 Java 项目中,生成的合约包装器位于 build/ generated/sources/web3j/main/ 中
我们将使用 Pimlico 作为捆绑器在 Sepolia 测试网上部署我们的帐户:
然后我们导入生成的合约包装器并使用deploy()方法来部署它:
这将部署智能帐户合约并记录其地址。我们可以使用Sepolia Etherscan来验证部署的地址。
第 3 部分:在智能账户之间发送 ETH
要测试在两个智能账户之间发送资金,我们首先需要部署另一个账户。
重复部署步骤并存储第二个地址。再次:
通过在链上部署我们的智能帐户,我们现在可以通过将 UserOperation 发送到我们的捆绑器来与其交互。
让我们尝试在我们部署的两个账户之间发送一些 ETH。我们正在使用execute()函数,所以首先我们需要对其进行编码:
然后我们需要构造一个UserOperation(EIP4337Transaction):
我们将气田留空的原因是我们可以使用捆绑器中的 ethEstimateUserOperationGas API 获得估计值。
当发送用户操作时:
捆绑器接收它并在本地模拟它以确保它会成功。如果有效,捆绑器会将其发送到 EntryPoint 合约。 EntryPoint 在您的智能帐户上调用 validateUserOp()。该函数检查授权(例如,通过签名)。
它确保智能账户有足够的余额来支付天然气。如果没有,它会调用智能帐户发送所需的预付款。然后,EntryPoint 调用您的智能帐户上的函数。
EIP-4337 引入了一种新的交易类型(UserOperation),该交易类型不直接由用户的 EOA 支付。相反,EntryPoint 合约需要预付款——一笔预付款,用于支付 UserOperation 的 Gas 成本。这笔存款必须来自 EntryPoint 合约中智能账户的余额。如果智能账户缺少足够的资金,则需要在 validateUserOp() 中预先充值缺少的金额。
我们可以通过这种预充值存款机制手动为部署的账户提供 ETH 资金,以支付其运营的 Gas 成本。
