ERC-7579是以太坊上一个模块化智能账户的标准,旨在通过定义智能账户及其模块的最小接口和行为来实现互操作性,解决智能账户实现碎片化的问题。它建立在账户抽象(ERC-4337)的基础上,确保跨不同提供商的互操作性,并简化模块的开发和使用,文章还介绍了该标准的组件、工作原理,并通过代码示例展示如何在Safe智能账户上实现和使用ERC-7579。
在快速发展的区块链技术世界中,智能账户已成为传统外部拥有账户 (EOA) 的强大替代品。与依赖私钥的 EOA 不同,智能账户是可编程的智能合约,可实现高级功能,例如无 Gas 交易、自定义验证逻辑和模块化扩展。然而,智能账户实现中缺乏标准化导致了碎片化、供应商锁定和兼容性问题。
ERC-7579 横空出世,这是一个变革性的以太坊标准,标题为“最小模块化智能账户”。ERC-7579 由 Rhinestone、Biconomy、ZeroDev 和 OKX 合作于 2023 年 12 月提出,通过为模块化智能账户及其模块定义最小接口和行为来解决这些挑战。ERC-7579 以账户抽象 (ERC-4337) 的原则为基础,确保了 Safe、Biconomy、ZeroDev 和 Kernel 等提供商之间的互操作性,从而培养了一个有凝聚力的生态系统。
这本综合指南深入探讨了 ERC-7579,探索了其技术组件、用例、实现细节和未来影响。本文包含代码片段、图表和最佳实践,是你理解和利用 ERC-7579 构建下一代区块链应用程序的首选资源。
ERC-7579 是一项以太坊改进提案 (EIP),它概述了模块化智能账户及其关联模块的最小必需接口和行为。它不规定智能账户如何在内部工作,而是标准化它们的外部接口,使模块开发人员能够创建与任何符合 ERC-7579 的账户兼容的可重用组件。这确保了为一个提供商(例如,Safe)构建的模块可以与其他提供商(例如,Biconomy、ZeroDev)无缝协作。
将智能账户想象成乐高底板,模块想象成乐高积木。正如乐高积木可以卡在任何兼容的底板上以创建不同的结构一样,ERC-7579 模块可以插入任何符合标准的智能账户中,以增强其功能。这个生态系统中的主要参与者包括:
对于 Safe 账户,需要一个 Safe7579 Adapter(由 Safe 和 Rhinestone 开发)来确保 ERC-7579 的兼容性。
在 ERC-7579 之前,智能账户的实现是分散的,导致了重大的挑战:
ERC-7579 通过提供通用标准来解决这些问题,从而提供以下好处:
标准化对于扩大智能账户的采用至关重要。如果没有 ERC-7579,开发者将面临:
ERC-7579 通过建立通用接口来解决这些问题,从而实现:
ERC-7579 定义了智能账户和四种模块类型的接口:验证器、执行器、回退处理程序和Hook。它利用 ERC-4337 进行账户抽象,从而确保支持用户操作和无 Gas 交易。下面是其组件和工作流程的详细分解。
符合 ERC-7579 的智能账户必须实现以下接口:
IERC7579AccountConfig:
accountId()
: 返回一个唯一的标识符 (例如, "safe.account.v1.0.0").supportsExecutionMode(bytes32 mode)
: 检查账户是否支持特定的执行模式。supportsModule(uint256 moduleTypeId)
: 验证对模块类型的支持 (1 代表验证器,2 代表执行器,等等)。执行功能:
execute(bytes32 mode, address target, uint256 value, bytes calldata data)
: 使用指定的模式执行交易 (例如,单次调用,批量调用,委托调用)。executeFromExecutor(bytes32 mode, address target, uint256 value, bytes calldata data)
: 允许执行器模块启动交易。executeUserOp(bytes calldata userOp)
(可选): 支持 ERC-4337 用户操作。模块管理:
installModule(uint256 moduleTypeId, address module, bytes calldata initData)
: 安装模块并发出一个 ModuleInstalled
事件。uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData, address sentinel)
: 移除模块并发出一个 ModuleUninstalled
事件。isModuleInstalled(uint256 moduleTypeId, address module)
: 检查是否安装了模块。ERC-7579 定义了四种模块类型,每种类型都有特定的角色:
validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
: 验证 ERC-4337 用户操作。isValidSignatureWithSender(bytes32 hash, bytes calldata signature, address sender)
: 支持 ERC-1271 签名验证。preCheck(address sender, bytes calldata data)
: 在执行之抢跑。postCheck(bytes calldata returnData)
: 在执行之后运行。每个模块都实现 IERC7579Module
接口:
onInstall(bytes calldata data)
: 初始化模块。onUninstall(bytes calldata data)
: 反初始化模块。isModuleType(uint256 moduleTypeId)
: 确认模块类型。isInitialized(address account)
: 检查是否为账户初始化了模块。执行模式被编码为 bytes32
值,指定了如何处理交易。它们包括:
CALL
(0x00),用于委托调用的 DELEGATECALL
(0x01)。DEFAULT
(0x00),用于错误时恢复的 REVERT
(0x01)。例如,模式可以被编码为:
0x0000000100000000000000000000000000000000000000000000000000000000
callType = DELEGATECALL
, execType = DEFAULT
, modeSelector = 0x00
, modePayload = 0x00
。本节演示如何创建一个符合 ERC-7579 的 Safe 智能账户,安装一个 OwnableExecutor
模块,并使用 permissionless.js
库执行交易。
创建一个 Node.js 项目并安装依赖项。
mkdir erc7579-safe-demo
cd erc7579-safe-demo
npm init -y
npm install permissionless viem ethers @safe-global/protocol-kit
下面是一个示例 OwnableExecutor
模块,该模块允许指定的所有者执行交易。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC7579.sol";
contract OwnableExecutor is IERC7579Module {
address public owner;
function onInstall(bytes calldata data) external override {
owner = abi.decode(data, (address));
require(owner != address(0), "Invalid owner");
}
function onUninstall(bytes calldata data) external override {
owner = address(0);
}
function isModuleType(uint256 moduleTypeId) external view override returns (bool) {
return moduleTypeId == 2; // 执行器
}
function isInitialized(address account) external view override returns (bool) {
return owner != address(0);
}
function executeOnOwnedAccount(address target, uint256 value, bytes calldata data) external {
require(msg.sender == owner, "Not authorized");
(bool success, ) = target.call{value: value}(data);
require(success, "Execution failed");
}
}
将此合约部署到测试网 (例如,Sepolia) 并记下其地址 (例如,0x4Fd8d57b94966982B62e9588C27B4171B55E8354
)。
创建一个脚本 ( index.js
) 来部署 Safe 账户,安装模块并执行交易。
// index.js
import { createPublicClient, http, encodePacked, parseEther } from "viem";
import { sepolia } from "viem/chains";
import { createSmartAccountClient, toSafeSmartAccount, erc7579Actions } from "permissionless";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { entryPoint07Address } from "viem/account-abstraction";
const apiKey = "YOUR_PIMLICO_API_KEY";
const bundlerUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`;
const ownerPrivateKey = "YOUR_PRIVATE_KEY"; // 替换为你的测试网私钥
const ownerAddress = "0xYourOwnerAddress"; // 从私钥派生
const recipientAddress = "0xRecipientAddress"; // 替换为收件人地址
// 创建客户端
const publicClient = createPublicClient({
transport: http("https://sepolia.rpc.thirdweb.com"),
});
const pimlicoClient = createPimlicoClient({
transport: http(bundlerUrl),
entryPoint: { address: entryPoint07Address, version: "0.7" },
});
// 创建 Safe 账户
async function createSafeAccount() {
const safeAccount = await toSafeSmartAccount({
client: publicClient,
owners: [ownerAddress],
version: "1.4.1",
entryPoint: { address: entryPoint07Address, version: "0.7" },
safe4337ModuleAddress: "0x7579EE8307284F293B1927136486880611F20002",
erc7579LaunchpadAddress: "0x7579011aB74c46090561ea277Ba79D510c6C00ff",
attesters: ["0x000000333034E9f539ce08819E12c1b8Cb29084d"], // Rhinestone attester
attestersThreshold: 1,
});
return safeAccount;
}
// 创建智能账户客户端
async function createClient(safeAccount) {
return createSmartAccountClient({
account: safeAccount,
chain: sepolia,
bundlerTransport: http(bundlerUrl),
paymaster: pimlicoClient,
userOperation: {
estimateFeesPerGas: async () => (await pimlicoClient.getUserOperationGasPrice()).fast,
},
}).extend(erc7579Actions());
}
// 安装 OwnableExecutor 模块
async function installModule(client) {
const ownableExecutorModule = "0x4Fd8d57b94966982B62e9588C27B4171B55E8354";
const moduleData = encodePacked(["address"], [ownerAddress]);
const userOpHash = await client.installModule({
type: "executor",
address: ownableExecutorModule,
context: moduleData,
});
const receipt = await pimlicoClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Module installed:", receipt);
}
// 执行交易
async function executeTransaction(client, safeAddress) {
const executeTxData = encodePacked(
["address", "uint256", "bytes"],
[recipientAddress, parseEther("0.1"), "0x"]
);
const userOpHash = await client.writeContract({
chain: sepolia,
account: safeAddress,
abi: [\
{\
name: "executeOnOwnedAccount",\
type: "function",\
inputs: [\
{ type: "address", name: "target" },\
{ type: "uint256", name: "value" },\
{ type: "bytes", name: "data" },\
],\
outputs: [],\
},\
],
functionName: "executeOnOwnedAccount",
args: [recipientAddress, parseEther("0.1"), "0x"],
address: "0x4Fd8d57b94966982B62e9588C27B4171B55E8354",
});
const receipt = await pimlicoClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Transaction executed:", receipt);
}
// 卸载模块
async function uninstallModule(client) {
const ownableExecutorModule = "0x4Fd8d57b94966982B62e9588C27B4171B55E8354";
const userOpHash = await client.uninstallModule({
type: "executor",
address: ownableExecutorModule,
context: "0x",
});
const receipt = await pimlicoClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Module uninstalled:", receipt);
}
// 主函数
async function main() {
const safeAccount = await createSafeAccount();
console.log("Safe account created:", safeAccount.address);
const client = await createClient(safeAccount);
await installModule(client);
await executeTransaction(client, safeAccount.address);
await uninstallModule(client);
}
main().catch(console.error);
YOUR_PIMLICO_API_KEY
、YOUR_PRIVATE_KEY
、YOUR_OWNER_ADDRESS
和 RECIPIENT_ADDRESS
替换为适当的值。node index.js
3. 该脚本将:
OwnableExecutor
模块。社交恢复模块 允许受信任的联系人 (监护人) 恢复用户的账户,从而增强安全性和可用性。以下是实现。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC7579.sol";
contract SocialRecovery is IERC7579Module {
mapping(address => bool) public guardians;
uint256 public guardianCount;
uint256 public threshold;
function onInstall(bytes calldata data) external override {
(address[] memory _guardians, uint256 _threshold) = abi.decode(data, (address[], uint256));
require(_threshold <= _guardians.length, "Invalid threshold");
for (uint256 i = 0; i < _guardians.length; i++) {
guardians[_guardians[i]] = true;
}
guardianCount = _guardians.length;
threshold = _threshold;
}
function onUninstall(bytes calldata data) external override {
guardianCount = 0;
threshold = 0;
}
function isModuleType(uint256 moduleTypeId) external view override returns (bool) {
return moduleTypeId == 1; // 验证器
}
function isInitialized(address account) external view override returns (bool) {
return guardianCount > 0;
}
function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
external
view
override
returns (uint256)
{
// 简化验证逻辑
return 0; // 有效
}
function isValidSignatureWithSender(bytes32 hash, bytes calldata signature, address sender)
external
view
override
returns (bytes4)
{
// 实现 ERC-1271 签名验证
return 0x1626ba7e; // 有效签名的 Magic value
}
function recover(address newOwner, address[] calldata approvals) external {
uint256 validApprovals = 0;
for (uint256 i = 0; i < approvals.length; i++) {
if (guardians[approvals[i]]) {
validApprovals++;
}
}
require(validApprovals >= threshold, "Insufficient approvals");
// 更新所有者逻辑 (例如,更新 Safe 所有者)
}
}
此模块允许用户设置监护人和阈值。如果用户失去访问权限,监护人可以批准新的所有者,从而确保账户恢复,而无需依赖单个私钥。
ERC-7579 的模块化架构支持广泛的应用程序:
Registry Hook
来批准安全模块。onUninstall
函数以防止状态损坏。ERC-7579 预计将通过以下方式彻底改变账户抽象生态系统:
Rhinestone 正在开发一个 模块市场,类似于智能账户的“App Store”,开发者可以在其中共享 ERC-7579 模块并从中获利。此市场将包括:
ERC-6900 由 Alchemy、Circle、Quantstamp 和 Ethereum 开发,是模块化智能账户的另一个标准。与 ERC-7579 的极简主义方法不同,ERC-6900 侧重于特定的安全和运营约束。虽然两者都旨在实现模块化,但 ERC-7579 优先考虑灵活性和互操作性,使其更适合于各种用例。
ERC-7579 鼓励通过新的 ERC 实现社区驱动的扩展,例如:
ERC-7579 是模块化智能账户的颠覆者,它提供了一个标准化、可互操作且灵活的框架,解决了智能账户实现的碎片化问题。通过与 ERC-4337 保持一致并启用可重用模块,它使开发者能够创建创新的区块链应用程序,同时确保 Safe、Biconomy、ZeroDev 和 Kernel 等提供商之间的无缝用户体验。该实现示例演示了如何部署 Safe 账户、安装 OwnableExecutor
模块并执行交易,而社交恢复模块则突出了高级用例。凭借其对互操作性、安全性和生态系统增长的关注,ERC-7579 将推动下一波区块链采用浪潮。
- 原文链接: medium.com/@ankitacode11...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!