Skip to content

Commit

Permalink
fix: [spearbit-69] reorder functions in plugins to be consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
fangting-alchemy committed Jan 22, 2024
1 parent a37331d commit 2329fb2
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 128 deletions.
66 changes: 33 additions & 33 deletions src/plugins/owner/MultiOwnerPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,36 +147,6 @@ contract MultiOwnerPlugin is BasePlugin, IMultiOwnerPlugin, IERC1271 {
return _1271_MAGIC_VALUE_FAILURE;
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc IMultiOwnerPlugin
function encodeMessageData(address account, bytes memory message)
public
view
override
returns (bytes memory)
{
bytes32 messageHash = keccak256(abi.encode(ERC6900_TYPEHASH, keccak256(message)));
return abi.encodePacked("\x19\x01", _domainSeparator(account), messageHash);
}

/// @inheritdoc IMultiOwnerPlugin
function getMessageHash(address account, bytes memory message) public view override returns (bytes32) {
return keccak256(encodeMessageData(account, message));
}

/// @inheritdoc IMultiOwnerPlugin
function isOwnerOf(address account, address ownerToCheck) public view returns (bool) {
return _owners.contains(account, CastLib.toSetValue(ownerToCheck));
}

/// @inheritdoc IMultiOwnerPlugin
function ownersOf(address account) public view returns (address[] memory) {
return CastLib.toAddressArray(_owners.getAll(account));
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Expand Down Expand Up @@ -363,9 +333,39 @@ contract MultiOwnerPlugin is BasePlugin, IMultiOwnerPlugin, IERC1271 {
return interfaceId == type(IMultiOwnerPlugin).interfaceId || super.supportsInterface(interfaceId);
}

// ┏━━━━━━━━━━━━━━━┓
// ┃ Internal ┃
// ┗━━━━━━━━━━━━━━━┛
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc IMultiOwnerPlugin
function isOwnerOf(address account, address ownerToCheck) public view returns (bool) {
return _owners.contains(account, CastLib.toSetValue(ownerToCheck));
}

/// @inheritdoc IMultiOwnerPlugin
function ownersOf(address account) public view returns (address[] memory) {
return CastLib.toAddressArray(_owners.getAll(account));
}

/// @inheritdoc IMultiOwnerPlugin
function encodeMessageData(address account, bytes memory message)
public
view
override
returns (bytes memory)
{
bytes32 messageHash = keccak256(abi.encode(ERC6900_TYPEHASH, keccak256(message)));
return abi.encodePacked("\x19\x01", _domainSeparator(account), messageHash);
}

/// @inheritdoc IMultiOwnerPlugin
function getMessageHash(address account, bytes memory message) public view override returns (bytes32) {
return keccak256(encodeMessageData(account, message));
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Internal Functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛

function _domainSeparator(address account) internal view returns (bytes32) {
return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, block.chainid, account, _SALT));
Expand Down
12 changes: 6 additions & 6 deletions src/plugins/session/ISessionKeyPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ interface ISessionKeyPlugin {
/// @param updates The abi-encoded updates to perform.
function updateKeyPermissions(address sessionKey, bytes[] calldata updates) external;

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin-only function
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ┃ Plugin state updating functions
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

/// @notice An externally available function, callable by anyone, that resets the "last used" timestamp on a
/// session key. This helps a session key get "unstuck" if it was used in a setting where every call it made
Expand All @@ -109,9 +109,9 @@ interface ISessionKeyPlugin {
/// @param sessionKey The session key to reset.
function resetSessionKeyGasLimitTimestamp(address account, address sessionKey) external;

// ┏━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ View functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━┛
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

/// @notice Get the session keys of the account.
/// This function is not added to accounts during installation.
Expand Down
169 changes: 80 additions & 89 deletions src/plugins/session/SessionKeyPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,53 +50,8 @@ contract SessionKeyPlugin is ISessionKeyPlugin, SessionKeyPermissions, BasePlugi
uint256 internal constant _MANIFEST_DEPENDENCY_INDEX_OWNER_RUNTIME_VALIDATION = 1;

// Storage fields

AssociatedLinkedListSet internal _sessionKeys;

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc BasePlugin
function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
external
override
returns (uint256)
{
if (functionId == uint8(FunctionId.USER_OP_VALIDATION_SESSION_KEY)) {
(Call[] memory calls, address sessionKey) = abi.decode(userOp.callData[4:], (Call[], address));
bytes32 hash = userOpHash.toEthSignedMessageHash();

(address recoveredSig, ECDSA.RecoverError err) = hash.tryRecover(userOp.signature);
if (err == ECDSA.RecoverError.NoError) {
if (
_sessionKeys.contains(msg.sender, CastLib.toSetValue(sessionKey)) && sessionKey == recoveredSig
) {
return _checkUserOpPermissions(userOp, calls, sessionKey);
}
return _SIG_VALIDATION_FAILED;
}
revert InvalidSignature(sessionKey);
}
revert NotImplemented();
}

/// @inheritdoc BasePlugin
function onUninstall(bytes calldata) external override {
// Unset the key id for all session keys.
address[] memory sessionKeys = CastLib.toAddressArray(_sessionKeys.getAll(msg.sender));
uint256 length = sessionKeys.length;
for (uint256 i = 0; i < length; ++i) {
_updateSessionKeyId(msg.sender, sessionKeys[i], SessionKeyId.wrap(bytes32(0)));

emit SessionKeyRemoved(msg.sender, sessionKeys[i]);
}

_sessionKeys.clear(msg.sender);
// Note that we do not reset the key id counter `_keyIdCounter` for the account, in order to prevent
// permissions configured from a previous installation from being re-used.
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Execution functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Expand Down Expand Up @@ -179,47 +134,54 @@ contract SessionKeyPlugin is ISessionKeyPlugin, SessionKeyPermissions, BasePlugi

// The function `updateKeyPermissions` is implemented in `SessionKeyPermissions`.

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin-only function
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ┃ Plugin state updating functions
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

// The function `resetSessionKeyGasLimitTimestamp` is implemented in `SessionKeyPermissions`.

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ┃ Plugin interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

/// @inheritdoc ISessionKeyPlugin
function sessionKeysOf(address account) external view override returns (address[] memory) {
SetValue[] memory values = _sessionKeys.getAll(account);
/// @inheritdoc BasePlugin
function onUninstall(bytes calldata) external override {
// Unset the key id for all session keys.
address[] memory sessionKeys = CastLib.toAddressArray(_sessionKeys.getAll(msg.sender));
uint256 length = sessionKeys.length;
for (uint256 i = 0; i < length; ++i) {
_updateSessionKeyId(msg.sender, sessionKeys[i], SessionKeyId.wrap(bytes32(0)));

return CastLib.toAddressArray(values);
}
emit SessionKeyRemoved(msg.sender, sessionKeys[i]);
}

/// @inheritdoc ISessionKeyPlugin
function isSessionKeyOf(address account, address sessionKey) external view override returns (bool) {
return _sessionKeys.contains(account, CastLib.toSetValue(sessionKey));
_sessionKeys.clear(msg.sender);
// Note that we do not reset the key id counter `_keyIdCounter` for the account, in order to prevent
// permissions configured from a previous installation from being re-used.
}

// ┏━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ View functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc ISessionKeyPlugin
function findPredecessor(address account, address sessionKey) external view override returns (bytes32) {
address[] memory sessionKeys = CastLib.toAddressArray(_sessionKeys.getAll(account));
/// @inheritdoc BasePlugin
function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
external
override
returns (uint256)
{
if (functionId == uint8(FunctionId.USER_OP_VALIDATION_SESSION_KEY)) {
(Call[] memory calls, address sessionKey) = abi.decode(userOp.callData[4:], (Call[], address));
bytes32 hash = userOpHash.toEthSignedMessageHash();

uint256 length = sessionKeys.length;
bytes32 predecessor = SENTINEL_VALUE;
for (uint256 i = 0; i < length; ++i) {
if (sessionKeys[i] == sessionKey) {
return predecessor;
(address recoveredSig, ECDSA.RecoverError err) = hash.tryRecover(userOp.signature);
if (err == ECDSA.RecoverError.NoError) {
if (
_sessionKeys.contains(msg.sender, CastLib.toSetValue(sessionKey)) && sessionKey == recoveredSig
) {
return _checkUserOpPermissions(userOp, calls, sessionKey);
}
return _SIG_VALIDATION_FAILED;
}

predecessor = bytes32(bytes20(sessionKeys[i]));
revert InvalidSignature(sessionKey);
}

revert SessionKeyNotFound(sessionKey);
revert NotImplemented();
}

/// @inheritdoc BasePlugin
Expand Down Expand Up @@ -347,19 +309,6 @@ contract SessionKeyPlugin is ISessionKeyPlugin, SessionKeyPermissions, BasePlugi
return metadata;
}

// ┏━━━━━━━━━━━━━━━┓
// ┃ EIP-165 ┃
// ┗━━━━━━━━━━━━━━━┛

/// @inheritdoc BasePlugin
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return interfaceId == type(ISessionKeyPlugin).interfaceId || super.supportsInterface(interfaceId);
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Internal Functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc BasePlugin
function _onInstall(bytes calldata data) internal override isNotInitialized(msg.sender) {
(address[] memory sessionKeysToAdd, bytes32[] memory tags,) =
Expand Down Expand Up @@ -397,9 +346,51 @@ contract SessionKeyPlugin is ISessionKeyPlugin, SessionKeyPermissions, BasePlugi
addSessionKey(sessionKeysToAdd[i], tags[i], permissionUpdates[i]);
}
}

/// @inheritdoc BasePlugin

function _isInitialized(address account) internal view override returns (bool) {
return !_sessionKeys.isEmpty(account);
}

// ┏━━━━━━━━━━━━━━━┓
// ┃ EIP-165 ┃
// ┗━━━━━━━━━━━━━━━┛

/// @inheritdoc BasePlugin
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return interfaceId == type(ISessionKeyPlugin).interfaceId || super.supportsInterface(interfaceId);
}

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc ISessionKeyPlugin
function sessionKeysOf(address account) external view override returns (address[] memory) {
SetValue[] memory values = _sessionKeys.getAll(account);

return CastLib.toAddressArray(values);
}

/// @inheritdoc ISessionKeyPlugin
function isSessionKeyOf(address account, address sessionKey) external view override returns (bool) {
return _sessionKeys.contains(account, CastLib.toSetValue(sessionKey));
}

/// @inheritdoc ISessionKeyPlugin
function findPredecessor(address account, address sessionKey) external view override returns (bytes32) {
address[] memory sessionKeys = CastLib.toAddressArray(_sessionKeys.getAll(account));

uint256 length = sessionKeys.length;
bytes32 predecessor = SENTINEL_VALUE;
for (uint256 i = 0; i < length; ++i) {
if (sessionKeys[i] == sessionKey) {
return predecessor;
}

predecessor = bytes32(bytes20(sessionKeys[i]));
}

revert SessionKeyNotFound(sessionKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {ISessionKeyPlugin} from "../ISessionKeyPlugin.sol";
import {SessionKeyPermissionsBase} from "./SessionKeyPermissionsBase.sol";

abstract contract SessionKeyPermissionsLoupe is SessionKeyPermissionsBase {
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ Plugin view functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc ISessionKeyPlugin
function getAccessControlType(address account, address sessionKey)
external
Expand Down

0 comments on commit 2329fb2

Please sign in to comment.