Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ERC-7484 registry adapter #3

Open
wants to merge 3 commits into
base: barz-v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion contracts/facets/V2MigrationFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,15 @@ contract V2MigrationFacet is BarzStorage {
});

IDiamondCut(address(this)).diamondCut(cut, address(0), "");
IMMSAFacet(address(this)).initMMSA();

address[] memory attesters = new address[](2);
attesters[0] = 0x0000000000000000000000000000000000000000; // Todo: Trust attester
attesters[1] = 0x000000333034E9f539ce08819E12c1b8Cb29084d; // Rhinestone attester
IMMSAFacet(address(this)).initMMSA({
registry: address(0x000000000069E2a187AEFFb852bF3cCdC95151B2),
attesters: attesters,
threshold: 1
});

emit V2MigrationComplete();
}
Expand Down
24 changes: 22 additions & 2 deletions contracts/facets/mmsa/MMSAFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {IValidator} from "./interfaces/IValidator.sol";
import {IModule} from "./interfaces/IModule.sol";
import {IHook} from "./interfaces/IHook.sol";
import {IMMSAFacet} from "./interfaces/IMMSAFacet.sol";
import {RegistryAdapter, IERC7484} from "./utils/RegistryAdapter.sol";

/**
* @title MMSA(Minimal Modular Smart Account) Facet
Expand All @@ -29,6 +30,7 @@ contract MMSAFacet is
ModuleManager,
ValidationManager,
Executor,
RegistryAdapter,
BarzStorage
{
using LibSentinelList for LibSentinelList.SentinelList;
Expand Down Expand Up @@ -64,8 +66,17 @@ contract MMSAFacet is
}
}

function initMMSA() external onlyEntryPointOrSelf {
function initMMSA(
address registry,
address[] calldata attesters,
uint8 threshold
) external onlyEntryPointOrSelf {
_initialize();
_configureRegistry({
registry: IERC7484(registry),
attesters: attesters,
threshold: threshold
});
}

function validateUserOp(
Expand Down Expand Up @@ -118,6 +129,7 @@ contract MMSAFacet is
override
onlyWhenUnlocked
withHook
withRegistry(msg.sender, EXECUTOR_MODULE_TYPE)
returns (bytes[] memory returnData)
{
if (!_isExecutorInstalled(msg.sender)) {
Expand Down Expand Up @@ -175,7 +187,15 @@ contract MMSAFacet is
uint256 _moduleTypeId,
address _module,
bytes calldata _initData
) external payable override onlyEntryPointOrSelf onlyWhenUnlocked withHook {
)
external
payable
override
onlyEntryPointOrSelf
onlyWhenUnlocked
withHook
withRegistry(_module, _moduleTypeId)
{
if (!IModule(_module).isModuleType(_moduleTypeId)) {
revert MMSAFacet__InvalidModule(_moduleTypeId, _module);
}
Expand Down
6 changes: 5 additions & 1 deletion contracts/facets/mmsa/interfaces/IMMSAFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ interface IMMSAFacet {
event ModuleInstalled(uint256 moduleTypeId, address module);
event ModuleUninstalled(uint256 moduleTypeId, address module);

function initMMSA() external;
function initMMSA(
address registry,
address[] memory attesters,
uint8 threshold
) external;

function installModule(
uint256 moduleTypeId,
Expand Down
50 changes: 50 additions & 0 deletions contracts/facets/mmsa/utils/RegistryAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IERC7484} from "../../../interfaces/ERC/IERC7484.sol";
import {LibMMSAStorage} from "../../../libraries/LibMMSAStorage.sol";

/**
* IERC7484 Registry adapter.
* this feature is opt-in. The smart account owner can choose to use the registry and which
* attesters to trust.
* @author zeroknots.eth | rhinestone.wtf
*/
abstract contract RegistryAdapter {
event ERC7484RegistryConfigured(address registry);

modifier withRegistry(address module, uint256 moduleType) {
_checkRegistry(module, moduleType);
_;
}

/**
* Check on ERC7484 Registry, if suffcient attestations were made
* This will revert, if not succicient valid attestations are on the registry
*/
function _checkRegistry(address module, uint256 moduleType) internal view {
IERC7484 registry = LibMMSAStorage.mmsaStorage().registry;
if (address(registry) != address(0)) {
// this will revert if attestations / threshold are not met
registry.checkForAccount(address(this), module, moduleType);
}
}

/**
* Configure ERC7484 Registry for Safe
*/
function _configureRegistry(
IERC7484 registry,
address[] calldata attesters,
uint8 threshold
) internal {
// sstore value in any case, as this function may be used to disable the use of registry
LibMMSAStorage.mmsaStorage().registry = registry;

// registry is an opt in feature for barz. if set, configure trusted attesters
if (address(registry) != address(0)) {
registry.trustAttesters(threshold, attesters);
}
emit ERC7484RegistryConfigured(address(registry));
}
}
54 changes: 54 additions & 0 deletions contracts/interfaces/ERC/IERC7484.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC7484 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* Check with Registry internal attesters */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

function check(address module) external view;

function checkForAccount(
address smartAccount,
address module
) external view;

function check(address module, uint256 moduleType) external view;

function checkForAccount(
address smartAccount,
address module,
uint256 moduleType
) external view;

/**
* Allows Smart Accounts - the end users of the registry - to appoint
* one or many attesters as trusted.
* @dev this function reverts, if address(0), or duplicates are provided in attesters[]
*
* @param threshold The minimum number of attestations required for a module
* to be considered secure.
* @param attesters The addresses of the attesters to be trusted.
*/
function trustAttesters(
uint8 threshold,
address[] calldata attesters
) external;

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* Check with external attester(s) */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

function check(
address module,
address[] calldata attesters,
uint256 threshold
) external view;

function check(
address module,
uint256 moduleType,
address[] calldata attesters,
uint256 threshold
) external view;
}
8 changes: 6 additions & 2 deletions contracts/libraries/LibMMSAStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
pragma solidity 0.8.26;

import {LibSentinelList} from "./LibSentinelList.sol";
import {IERC7484} from "../interfaces/ERC/IERC7484.sol";
import {IHook} from "../facets/mmsa/interfaces/IHook.sol";
import {ISigner} from "../facets/mmsa/interfaces/ISigner.sol";
import {CallType, PermissionId, PassFlag, PolicyData} from "../facets/mmsa/utils/Types.sol";

struct FallbackHandler {
address handler; ///< The address of the fallback function handler.
CallType calltype; ///< The type of call this handler supports (e.g., static or delegatecall).
address handler;
///< The address of the fallback function handler.
CallType calltype;
}
///< The type of call this handler supports (e.g., static or delegatecall).

struct PermissionConfig {
PassFlag permissionFlag;
Expand All @@ -24,6 +27,7 @@ struct MMSAStorage {
mapping(PermissionId => PermissionConfig) permissionConfig;
IHook hook;
bool isInitialized;
IERC7484 registry;
}

library LibMMSAStorage {
Expand Down