ERC-7484是以太坊改进提案,旨在为模块化智能账户和去中心化身份系统提供安全保障。它定义了模块注册中心和注册适配器的标准框架,通过链上认证来验证模块的安全性,并支持可验证凭证的撤销状态检查。该提案通过标准化接口,增强了互操作性、透明度和信任,从而促进安全、互操作和创新的解决方案。
以太坊区块链随着账户抽象和模块化智能账户的引入而获得了显著发展,这些账户已通过 ERC-7579 进行了标准化。这些账户允许开发者通过即插即用的模块扩展功能,从而实现高级身份验证、自动交易或合规性检查等功能。然而,模块化系统的灵活性带来了安全风险,因为未经验证的或恶意模块可能会危及账户的完整性。ERC-7484 由 Konrad Kopp 和 zeroknots 于 2023 年 8 月提出,通过标准化模块注册表和注册表适配器来解决这一挑战,以在集成之前验证模块的安全性。本文深入探讨了 ERC-7484,涵盖了其目的、技术实施、用例、代码示例及其在模块化智能账户和去中心化身份系统中的作用。
ERC-7484 是一项以太坊改进提案 (EIP),它定义了一个标准化的框架,用于在符合 ERC-7579 的模块化智能账户中安全地集成模块。它引入了两个主要组成部分:模块注册表,它存储关于模块安全性的链上证明;以及注册表适配器,它使智能账户能够查询和验证这些证明。除了智能账户外,ERC-7484 还通过提供用于检查可验证凭证 (VC) 吊销状态的接口来支持去中心化身份系统,从而与 Web3 中的自我主权身份 (SSI) 原则保持一致。

ERC-7484 服务于两个不同但相关的目的:
ERC-7579 使开发者能够创建模块化智能账户,这些账户可以集成第三方模块以扩展功能。然而,这种可组合性带来了风险:
在 Web3 中,可验证凭证 (VC) 用于去中心化身份,例如 KYC 文档或认证。与中心化系统不同,没有单一机构来管理凭证吊销。这就需要:
ERC-7484 通过提供统一的框架来安全地集成模块和验证凭证状态,从而应对了这些挑战。
以下是 ERC-7484 的两种用例的详细实现,并带有代码片段来说明这些概念。
模块注册表存储证明并提供查询模块状态的函数。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IModuleRegistry {
// 事件
event AttestationCreated(address indexed module, address indexed attester, bytes32 schema, bytes data);
event AttestationRevoked(address indexed module, address indexed attester, bytes32 schema);
// 用于存储证明数据的结构体
struct AttestationData {
address attester;
bytes32 schema;
bytes data;
uint256 expiry;
}
// 添加一个证明
function attest(address module, bytes32 schema, bytes calldata data, uint256 expiry) external;
// 撤销一个证明
function revokeAttestation(address module, bytes32 schema) external;
// 获取模块的所有证明
function getAttestations(address module) external view returns (AttestationData[] memory);
// 检查模块是否被特定的证明者证明
function isAttested(address module, address attester, bytes32 schema) external view returns (bool);
// 检查单个证明者
function check(address module, address attester) external view returns (bool);
// 检查多个证明者
function checkN(address module, address[] calldata attesters) external view returns (bool);
}
解释:
AttestationData: 存储关于证明的详细信息,包括证明者、模式(例如,“securityAuditPassed”)、数据和到期时间。attest: 允许证明者提交证明。revokeAttestation: 允许证明者撤销他们的证明。getAttestations: 返回模块的所有证明。isAttested: 检查特定的证明者是否已证明模块的给定模式。check 和 checkN: 分别验证来自一个或多个证明者的证明。模块注册表的一个简化实现:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ModuleRegistry is IModuleRegistry {
mapping(address => AttestationData[]) private moduleAttestations;
function attest(address module, bytes32 schema, bytes calldata data, uint256 expiry) external override {
require(module != address(0), "Invalid module address"); // 无效的模块地址
require(expiry == 0 || expiry > block.timestamp, "Invalid expiry"); // 无效的到期时间
moduleAttestations[module].push(AttestationData({
attester: msg.sender,
schema: schema,
data: data,
expiry: expiry
}));
emit AttestationCreated(module, msg.sender, schema, data);
}
function revokeAttestation(address module, bytes32 schema) external override {
for (uint256 i = 0; i < moduleAttestations[module].length; i++) {
if (moduleAttestations[module][i].attester == msg.sender && moduleAttestations[module][i].schema == schema) {
moduleAttestations[module][i] = moduleAttestations[module][moduleAttestations[module].length - 1];
moduleAttestations[module].pop();
emit AttestationRevoked(module, msg.sender, schema);
break;
}
}
}
function getAttestations(address module) external view override returns (AttestationData[] memory) {
return moduleAttestations[module];
}
function isAttested(address module, address attester, bytes32 schema) external view override returns (bool) {
for (uint256 i = 0; i < moduleAttestations[module].length; i++) {
AttestationData memory attestation = moduleAttestations[module][i];
if (attestation.attester == attester && attestation.schema == schema && (attestation.expiry == 0 || attestation.expiry > block.timestamp)) {
return true;
}
}
return false;
}
function check(address module, address attester) external view override returns (bool) {
return isAttested(module, attester, keccak256("securityAuditPassed"));
}
function checkN(address module, address[] calldata attesters) external view override returns (bool) {
for (uint256 i = 0; i < attesters.length; i++) {
if (!isAttested(module, attesters[i], keccak256("securityAuditPassed"))) {
return false;
}
}
return true;
}
}
注册表适配器查询模块注册表并强制执行安全标准。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract RegistryAdapter {
IModuleRegistry public registry;
uint256 public minAttestations;
address[] public trustedAttesters;
constructor(address _registry, uint256 _minAttestations, address[] memory _trustedAttesters) {
registry = IModuleRegistry(_registry);
minAttestations = _minAttestations;
trustedAttesters = _trustedAttesters;
}
function validateModule(address module) external view returns (bool) {
// 检查模块是否有足够的证明
uint256 validAttestations = 0;
for (uint256 i = 0; i < trustedAttesters.length; i++) {
if (registry.check(module, trustedAttesters[i])) {
validAttestations++;
}
}
return validAttestations >= minAttestations;
}
}
智能账户使用适配器来验证模块。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SmartAccount {
RegistryAdapter public adapter;
mapping(address => bool) public enabledModules;
constructor(address _adapter) {
adapter = RegistryAdapter(_adapter);
}
function enableModule(address module) external {
require(adapter.validateModule(module), "Module not verified"); // 模块未验证
enabledModules[module] = true;
}
function executeModuleFunction(address module, bytes calldata data) external {
require(enabledModules[module], "Module not enabled"); // 模块未启用
(bool success,) = module.delegatecall(data);
require(success, "Module execution failed"); // 模块执行失败
}
}
用于检查 VC 吊销状态的接口非常简洁但功能强大。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC7484 {
function isRevoked(bytes32 credentialId) external view returns (bool);
}
用于管理 VC 吊销状态的基本实现:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CredentialStatusRegistry is IERC7484 {
address public issuer;
mapping(bytes32 => bool) private revoked;
modifier onlyIssuer() {
require(msg.sender == issuer, "Not authorized"); // 未授权
_;
}
constructor() {
issuer = msg.sender;
}
function revokeCredential(bytes32 credentialId) external onlyIssuer {
revoked[credentialId] = true;
}
function isRevoked(bytes32 credentialId) external view override returns (bool) {
return revoked[credentialId];
}
}
DApp 可以使用 Ethers.js 检查 VC 状态:
import { ethers } from "ethers";
const contractAddress = "0xYourContractAddress";
const abi = ["function isRevoked(bytes32 credentialId) external view returns (bool)"];
const provider = new ethers.providers.JsonRpcProvider("<https://rpc.sepolia.org>");
const contract = new ethers.Contract(contractAddress, abi, provider);
async function checkCredentialStatus(vcId: string) {
const credentialHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(vcId));
const revoked = await contract.isRevoked(credentialHash);
console.log(`Credential is ${revoked ? "revoked" : "valid"}`); // 凭证是 ${revoked ? "已吊销" : "有效"}
return !revoked;
}
用户想要向他们的智能账户添加一个质押模块:
作为一项草案提案,ERC-7484 受社区反馈和改进的约束。潜在的进展包括:
ERC-7484 是以太坊生态系统的一项关键标准,它解决了模块化智能账户和去中心化身份系统中的关键安全和信任挑战。通过标准化模块注册表和注册表适配器,它可以确保安全地集成模块,而其 VC 接口可以实现无需信任的凭证验证。提供的代码片段和用例展示了它的实际适用性,从质押模块到 DeFi 中的 KYC。随着以太坊的账户抽象和 SSI 格局的发展,ERC-7484 将在促进安全、可互操作和创新的解决方案方面发挥至关重要的作用。
- 原文链接: medium.com/@ankitacode11...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!