Skip to content

Commit

Permalink
chore: move common stateful session functionality to StatefulSessionK…
Browse files Browse the repository at this point in the history
…eyManagerBase
  • Loading branch information
ankurdubey521 committed Dec 4, 2023
1 parent 5cc20b1 commit 6acc584
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IStatefulSessionKeyManagerBase} from "./IStatefulSessionKeyManagerBase.sol";

/**
* @title Session Key Manager module for Biconomy Modular Smart Accounts.
* @dev TODO
* @dev Similar to the Stateful Session Key Manager module, but the session enable transaction
* is batched with the first transaction that uses the session key.
* Session creation is offline and completely free.
* @author Ankur Dubey - <[email protected]>
* @author Fil Makarov - <[email protected]>
*/
interface ISessionKeyManagerModuleHybrid {
struct SessionData {
uint48 validUntil;
uint48 validAfter;
address sessionValidationModule;
bytes sessionKeyData;
}

interface ISessionKeyManagerModuleHybrid is IStatefulSessionKeyManagerBase {
/**
* @dev validates that Session Key + parameters are enabled
* by being included into the merkle tree
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IStatefulSessionKeyManagerBase} from "./IStatefulSessionKeyManagerBase.sol";

/**
* @title Session Key Manager module for Biconomy Modular Smart Accounts.
* @dev TODO
* @title Stateful Session Key Manager module for Biconomy Modular Smart Accounts.
* @dev Stores the session key data on-chain to save calldata costs in subsequent transactions.
* This module is optimised for L2s where calldata is expensive and hence session key data is stored on-chain.
* @author Ankur Dubey - <[email protected]>
* @author Fil Makarov - <[email protected]>
*/
interface ISessionKeyManagerModuleStateful {
struct SessionData {
uint48 validUntil;
uint48 validAfter;
address sessionValidationModule;
bytes sessionKeyData;
}

interface ISessionKeyManagerModuleStateful is IStatefulSessionKeyManagerBase {
/**
* @dev validates that Session Key + parameters are enabled
* by being included into the merkle tree
Expand All @@ -28,8 +23,8 @@ interface ISessionKeyManagerModuleStateful {
) external;

/**
* @dev enables session key for a smart account
* @dev creates a session for a smart account
* @param sessionData session data
*/
function enableSessionKey(SessionData calldata sessionData) external;
function enableSession(SessionData calldata sessionData) external;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
* @title IStatefulSessionKeyManagerBase
* @dev Base contract for Session Key Manager Modules that store the session
* key data on-chain.
* These Session Key Manager module are typically optimised for L2s where calldata
* is expensive and hence session key data is stored on-chain.
* @author Ankur Dubey - <[email protected]>
*/
interface IStatefulSessionKeyManagerBase {
struct SessionData {
uint48 validUntil;
uint48 validAfter;
address sessionValidationModule;
bytes sessionKeyData;
}

event SessionCreated(
address indexed sa,
bytes32 indexed sessionDataDigest,
SessionData data
);

event SessionDisabled(
address indexed sa,
bytes32 indexed sessionDataDigest
);

/**
* @notice Explicity disable a session. Can be useful is situations where a session
* needs to be disabled before it expires.
* @param _sa smart account for which session key is being disabled
* @param _sessionDigest digest of session key data
*/
function disableSession(address _sa, bytes32 _sessionDigest) external;

/**
* @notice Returns session data for a given session digest and smart account
* @param _sessionDataDigest digest of session key data
* @param _sa smart account for which session key is being disabled
* @return data SessionData struct
*/
function enabledSessionsData(
bytes32 _sessionDataDigest,
address _sa
) external view returns (SessionData memory data);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity ^0.8.20;

import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {ISessionValidationModule} from "../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModule} from "../interfaces/modules/ISessionKeyManagerModule.sol";
import {ISessionKeyManagerModule} from "../interfaces/modules/SessionKeyManagers/ISessionKeyManagerModule.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {BaseAuthorizationModule} from "../BaseAuthorizationModule.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {ISessionValidationModule} from "../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModule} from "../interfaces/modules/ISessionKeyManagerModule.sol";
import {IAuthorizationModule} from "../interfaces/IAuthorizationModule.sol";
import {ISignatureValidator} from "../interfaces/ISignatureValidator.sol";
import {ISessionValidationModule} from "../../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModule} from "../../interfaces/modules/SessionKeyManagers/ISessionKeyManagerModule.sol";
import {IAuthorizationModule} from "../../interfaces/IAuthorizationModule.sol";
import {ISignatureValidator} from "../../interfaces/ISignatureValidator.sol";

/**
* @title Session Key Manager module for Biconomy Modular Smart Accounts.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {ISessionValidationModule} from "../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModuleStateful} from "../interfaces/modules/ISessionKeyManagerModuleStateful.sol";
import {IAuthorizationModule} from "../interfaces/IAuthorizationModule.sol";
import {ISignatureValidator} from "../interfaces/ISignatureValidator.sol";
import {ISessionValidationModule} from "../../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModuleStateful} from "../../interfaces/modules/SessionKeyManagers/ISessionKeyManagerModuleStateful.sol";
import {StatefulSessionKeyManagerBase} from "./StatefulSessionKeyManagerBase.sol";

/**
* @title Session Key Manager module for Biconomy Modular Smart Accounts.
Expand All @@ -17,18 +15,14 @@ import {ISignatureValidator} from "../interfaces/ISignatureValidator.sol";
*/

contract SessionKeyManagerStateful is
BaseAuthorizationModule,
StatefulSessionKeyManagerBase,
ISessionKeyManagerModuleStateful
{
// Inverting the order of the mapping seems to make it non-compliant with the bundlers
mapping(bytes32 sessionDataDigest => mapping(address sa => SessionData data))
public enabledSessions;

/// @inheritdoc IAuthorizationModule
/// @inheritdoc StatefulSessionKeyManagerBase
function validateUserOp(
UserOperation calldata userOp,
bytes32 userOpHash
) external virtual returns (uint256 rv) {
) external virtual override returns (uint256 rv) {
(bytes memory moduleSignature, ) = abi.decode(
userOp.signature,
(bytes, address)
Expand All @@ -39,9 +33,9 @@ contract SessionKeyManagerStateful is

validateSessionKey(userOp.sender, sessionDataDigest);

SessionData storage sessionData = enabledSessions[sessionDataDigest][
userOp.sender
];
SessionData storage sessionData = _enabledSessionsData[
sessionDataDigest
][userOp.sender];

rv = _packValidationData(
//_packValidationData expects true if sig validation has failed, false otherwise
Expand All @@ -58,9 +52,7 @@ contract SessionKeyManagerStateful is
}

/// @inheritdoc ISessionKeyManagerModuleStateful
function enableSessionKey(
SessionData calldata sessionData
) external override {
function enableSession(SessionData calldata sessionData) external override {
bytes32 sessionDataDigest = keccak256(
abi.encodePacked(
sessionData.validUntil,
Expand All @@ -69,7 +61,8 @@ contract SessionKeyManagerStateful is
sessionData.sessionKeyData
)
);
enabledSessions[sessionDataDigest][msg.sender] = sessionData;
_enabledSessionsData[sessionDataDigest][msg.sender] = sessionData;
emit SessionCreated(msg.sender, sessionDataDigest, sessionData);
}

/// @inheritdoc ISessionKeyManagerModuleStateful
Expand All @@ -78,27 +71,9 @@ contract SessionKeyManagerStateful is
bytes32 sessionKeyDataDigest
) public virtual override {
require(
enabledSessions[sessionKeyDataDigest][smartAccount]
_enabledSessionsData[sessionKeyDataDigest][smartAccount]
.sessionValidationModule != address(0),
"SKM: Session Key is not enabled"
);
}

/// @inheritdoc ISignatureValidator
function isValidSignature(
bytes32 _dataHash,
bytes memory _signature
) public pure override returns (bytes4) {
(_dataHash, _signature);
return 0xffffffff; // do not support it here
}

/// @inheritdoc ISignatureValidator
function isValidSignatureUnsafe(
bytes32 _dataHash,
bytes memory _signature
) public pure override returns (bytes4) {
(_dataHash, _signature);
return 0xffffffff; // do not support it here
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,30 @@ pragma solidity ^0.8.20;

/* solhint-disable function-max-lines */

import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {ISessionValidationModule} from "../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModuleHybrid} from "../interfaces/modules/ISessionKeyManagerModuleHybrid.sol";
import {IAuthorizationModule} from "../interfaces/IAuthorizationModule.sol";
import {ISignatureValidator, EIP1271_MAGIC_VALUE} from "../interfaces/ISignatureValidator.sol";
import {ISessionValidationModule} from "../../interfaces/modules/ISessionValidationModule.sol";
import {ISessionKeyManagerModuleHybrid} from "../../interfaces/modules/SessionKeyManagers/ISessionKeyManagerModuleHybrid.sol";
import {ISignatureValidator, EIP1271_MAGIC_VALUE} from "../../interfaces/ISignatureValidator.sol";
import {StatefulSessionKeyManagerBase} from "./StatefulSessionKeyManagerBase.sol";

/**
* @title Session Key Manager module for Biconomy Modular Smart Accounts.
* @dev TODO
* @dev Similar to the Stateful Session Key Manager module, but the session enable transaction
* is batched with the first transaction that uses the session key.
* Session creation is offline and completely free.
* @author Ankur Dubey - <[email protected]>
* @author Fil Makarov - <[email protected]>
*/
contract SessionKeyManagerHybrid is
BaseAuthorizationModule,
StatefulSessionKeyManagerBase,
ISessionKeyManagerModuleHybrid
{
mapping(bytes32 sessionDataDigest => mapping(address sa => SessionData data))
public enabledSessions;

/// @inheritdoc IAuthorizationModule
/// @inheritdoc StatefulSessionKeyManagerBase
function validateUserOp(
UserOperation calldata userOp,
bytes32 userOpHash
) external virtual returns (uint256 rv) {
) external virtual override returns (uint256 rv) {
(bytes memory moduleSignature, ) = abi.decode(
userOp.signature,
(bytes, address)
Expand Down Expand Up @@ -97,7 +95,7 @@ contract SessionKeyManagerHybrid is

validateSessionKeyPreEnabled(userOp.sender, sessionDataDigest);

SessionData storage sessionData = enabledSessions[
SessionData storage sessionData = _enabledSessionsData[
sessionDataDigest
][userOp.sender];

Expand Down Expand Up @@ -197,12 +195,14 @@ contract SessionKeyManagerHybrid is
sessionKeyData
)
);
enabledSessions[sessionDataDigest][msg.sender] = SessionData({
SessionData memory sessionData = SessionData({
validUntil: validUntil,
validAfter: validAfter,
sessionValidationModule: sessionValidationModule,
sessionKeyData: sessionKeyData
});
_enabledSessionsData[sessionDataDigest][msg.sender] = sessionData;
emit SessionCreated(msg.sender, sessionDataDigest, sessionData);
}

/// @inheritdoc ISessionKeyManagerModuleHybrid
Expand All @@ -211,27 +211,9 @@ contract SessionKeyManagerHybrid is
bytes32 sessionKeyDataDigest
) public virtual override {
require(
enabledSessions[sessionKeyDataDigest][smartAccount]
_enabledSessionsData[sessionKeyDataDigest][smartAccount]
.sessionValidationModule != address(0),
"SKM: Session key is not enabled"
);
}

/// @inheritdoc ISignatureValidator
function isValidSignature(
bytes32 _dataHash,
bytes memory _signature
) public pure override returns (bytes4) {
(_dataHash, _signature);
return 0xffffffff; // do not support it here
}

/// @inheritdoc ISignatureValidator
function isValidSignatureUnsafe(
bytes32 _dataHash,
bytes memory _signature
) public pure override returns (bytes4) {
(_dataHash, _signature);
return 0xffffffff; // do not support it here
}
}
Loading

0 comments on commit 6acc584

Please sign in to comment.