Skip to content

Commit

Permalink
helper utils , types and dev notes for create session
Browse files Browse the repository at this point in the history
  • Loading branch information
livingrockrises committed Sep 11, 2024
1 parent 1f8bb85 commit e2fd99e
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 29 deletions.
29 changes: 27 additions & 2 deletions src/modules/utils/SmartSessionHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import addresses from "../../__contracts/addresses.js"
import { type AnyReferenceValue, parseReferenceValue } from "./Helper"
import { type EnableSessionData, type Session, SmartSessionMode, type SmartSessionModeType } from "./Types"
import { LibZip } from 'solady'
import { abi, encodeEnableSessionSignatureAbi } from "./abi"
import { smartSessionAbi, encodeEnableSessionSignatureAbi, universalActionPolicyAbi } from "./abi"

export type Rule = {
/**
Expand Down Expand Up @@ -169,7 +169,7 @@ export const formatPermissionEnableSig = ({
}) => {
return (await client.readContract({
address: addresses.SmartSession, // Review address import
abi,
abi: smartSessionAbi,
functionName: 'getPermissionId',
args: [session],
})) as string
Expand Down Expand Up @@ -246,3 +246,28 @@ export const encodeSmartSessionSignature = ({
throw new Error(`Unknown mode ${mode}`)
}
}

// Note: this helper gives you policy data for a universal action policy
// PolicyData is a struct that contains the policy address and the init data
// Action config requires param rules. we should have a way to build rules next
export const getUniversalActionPolicy = (
actionConfig: ActionConfig,
): Policy => {
if (actionConfig.paramRules.rules.length > MAX_RULES) {
throw new Error(`Max number of rules is ${MAX_RULES}`)
}

return {
address: addresses.UniActionPolicy,
initData: encodeAbiParameters(universalActionPolicyAbi, [
{
valueLimitPerUse: actionConfig.valueLimitPerUse,
paramRules: {
length: actionConfig.paramRules.length,
rules: actionConfig.paramRules.rules,
},
},
]),
deInitData: '0x',
}
}
71 changes: 64 additions & 7 deletions src/modules/utils/Types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Address, Chain, Hex } from "viem"
import type { AbiFunction, Address, Chain, Hex } from "viem"
import type {
CallType,
SimulationType,
SmartAccountSigner,
SupportedSigner,
UserOperationStruct
} from "../../account"
import { Rule } from "./SmartSessionHelpers"
export type ModuleVersion = "1.0.0-beta" // | 'V1_0_1'

export interface BaseValidationModuleConfig {
Expand Down Expand Up @@ -245,12 +246,12 @@ export const moduleTypeIds: ModuleTypeIds = {
// Note: can import from ModuleKit

export type Session = {
sessionValidator: Address
sessionValidatorInitData: Hex
salt: Hex
userOpPolicies: PolicyData[]
erc7739Policies: ERC7739Data
actions: ActionData[]
sessionValidator: Address // deployed SimpleSigner
sessionValidatorInitData: Hex // abi.encodePacked sessionKeyEOA
salt: Hex // random salt
userOpPolicies: PolicyData[] // empty policies by default
erc7739Policies: ERC7739Data // empty policies by default
actions: ActionData[] // make uni action policy
}

export type SessionEIP712 = {
Expand Down Expand Up @@ -314,3 +315,59 @@ export type EnableSessionData = {
// accountType: AccountType // Temp
}

// Types for creating session with abi SVM

// Note: keep Dan stuff for later
export type DanModuleInfo = {
/** Ephemeral sk */
jwt: string
/** eoa address */
eoaAddress: Hex
/** threshold */
threshold: number
/** parties number */
partiesNumber: number
/** userOp to be signed */
userOperation?: Partial<UserOperationStruct>
/** chainId */
chainId: number
/** selected mpc key id */
mpcKeyId: string
}

export interface CreateSessionDataParams {
// TimeLimitPolicy?
// /** window end for the session key */
// validUntil: number
// /** window start for the session key */
// validAfter: number
// /** Address of the session validation module */

// Note: below is only taking information specific to universal policy.
// Other two fields of seesions object (7739 policy and userOp policy will be empty by default)
// We should have means to get information on how to build those too

sessionPublicKey: Hex

sessionValidatorAddress: Address // constant for a type of validator

sessionKeyData: Hex

/** The address of the contract to be included in the policy */
contractAddress: Hex;

/** The specific function selector from the contract to be included in the policy */
functionSelector: string | AbiFunction;

/** The rules to be included in the policy */
rules: Rule[];

/** The maximum value that can be transferred in a single transaction */
valueLimit: bigint;

/** we generate uuid based sessionId. but if you prefer to track it on your side and attach custom session identifier this can be passed */
preferredSessionId?: string
/** Dan module info */
danModuleInfo?: DanModuleInfo
}

62 changes: 61 additions & 1 deletion src/modules/utils/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export const installSmartSessionsAbi = [
{ type: 'bytes' },
]

export const abi = [
export const smartSessionAbi = [
{
inputs: [{ internalType: 'uint256', name: 'index', type: 'uint256' }],
name: 'AssociatedArray_OutOfBounds',
Expand Down Expand Up @@ -1133,4 +1133,64 @@ export const installSmartSessionsAbi = [
type: 'function',
},
]

// Review redundancy
export const universalActionPolicyAbi = [
{
components: [
{
name: 'valueLimitPerUse',
type: 'uint256',
},
{
components: [
{
name: 'length',
type: 'uint256',
},
{
components: [
{
name: 'condition',
type: 'uint8',
},
{
name: 'offset',
type: 'uint64',
},
{
name: 'isLimited',
type: 'bool',
},
{
name: 'ref',
type: 'bytes32',
},
{
components: [
{
name: 'limit',
type: 'uint256',
},
{
name: 'used',
type: 'uint256',
},
],
name: 'usage',
type: 'tuple',
},
],
name: 'rules',
type: 'tuple[16]',
},
],
name: 'paramRules',
type: 'tuple',
},
],
name: 'ActionConfig',
type: 'tuple',
},
]

83 changes: 64 additions & 19 deletions src/modules/validators/SmartSessionModule.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { type Hex } from "viem"
import { encodeFunctionData, parseAbi, type Hex } from "viem"

Check failure on line 1 in src/modules/validators/SmartSessionModule.ts

View workflow job for this annotation

GitHub Actions / size report

'encodeFunctionData' is declared but its value is never read.
import addresses from "../../__contracts/addresses.js"
import type { SmartAccountSigner } from "../../account/index.js"
import { BaseValidationModule } from "../base/BaseValidationModule.js"
import { SmartSessionMode, type Module } from "../utils/Types.js"
import { CreateSessionDataParams, SmartSessionMode, type Module } from "../utils/Types.js"
import { encodeSmartSessionSignature } from "../utils/SmartSessionHelpers.js"
import { type Session } from "../utils/Types.js"

const DUMMY_ECDSA_SIG = "0xe8b94748580ca0b4993c9a1b86b5be851bfc076ff5ce3a1ff65bf16392acfcb800f9b4f1aef1555c7fce5599fffb17e7c635502154a0333ba21f3ae491839af51c";

const UNIVERSAL_POLICY_ADDRESS = addresses.UniversalPolicy

Check failure on line 11 in src/modules/validators/SmartSessionModule.ts

View workflow job for this annotation

GitHub Actions / size report

'UNIVERSAL_POLICY_ADDRESS' is declared but its value is never read.

// Note: flows: use mode and enable mode both should be supported.
export class SmartSessionModule extends BaseValidationModule {
// Notice: For smart sessions signer could be anything. Which is an implementation of ISessionValidator interface
// SmartAccountSigner works if session validator is K1 like single signer.
Expand All @@ -31,7 +35,8 @@ export class SmartSessionModule extends BaseValidationModule {
// Note: this second argument is like ModuleInfo object which is needed for certain modules like SKM for v2 account sdk
override async signUserOpHash(userOpHash: string, permissionId?: Hex): Promise<Hex>{
const signature = await this.signer.signMessage({ raw: userOpHash as Hex })


// Not this function is only implemented for USE mode.
return encodeSmartSessionSignature({
mode: SmartSessionMode.USE,
permissionId: permissionId ? permissionId : '0x',
Expand All @@ -47,22 +52,9 @@ export class SmartSessionModule extends BaseValidationModule {
}) as Hex
}

// Note:
// Needs more helpers to create a session struct. given constant validator, policies need to be built.
// Could be in helpers
// Todo:L
// Temp comment below
// To remind again how a session looks like..

/*Session memory session = Session({
sessionValidator: ISessionValidator(address(yesSigner)),
salt: salt,
sessionValidatorInitData: "mockInitData",
userOpPolicies: _getEmptyPolicyDatas(address(yesPolicy)),
erc7739Policies: _getEmptyERC7739Data("mockContent", _getEmptyPolicyDatas(address(yesPolicy))), // optional and default empty
actions: _getEmptyActionDatas(_target, MockTarget.setValue.selector, address(yesPolicy)) // mocks. but usually one universal policy is enough
});*/

/*
/*
[
{
sessionValidator: OWNABLE_VALIDATOR_ADDRESS as Address,
Expand Down Expand Up @@ -90,7 +82,60 @@ export class SmartSessionModule extends BaseValidationModule {
},
},
]
*/
*/

// Notice:
// This is a USE mode so we need calldata to post on smart session module to make sessions enabled first.
// For enable mode we will just need to preapre digest to sign and then make a userOperation that has actual session tx.

// Note: can later create methods like

createSessionData = async (
sessionRequestedInfo: CreateSessionDataParams[]

Check failure on line 94 in src/modules/validators/SmartSessionModule.ts

View workflow job for this annotation

GitHub Actions / size report

'sessionRequestedInfo' is declared but its value is never read.
): Promise<void> => {

// 1. iteraste over sessionRequestedInfo and make ActionConfig using the passed rules and value limit (calculate rules length and fit in object)

// 2. call getUniversalActionPolicy that will give you policy object

// 3. Build actionData from this policy object and contractAddress and func selector
// type is
/*export type ActionData = {
actionTargetSelector: Hex
actionTarget: Address
actionPolicies: PolicyData[]
}*/

// Build the session objects then apply below.

// Review
const smartSessionBI = parseAbi([

Check failure on line 112 in src/modules/validators/SmartSessionModule.ts

View workflow job for this annotation

GitHub Actions / size report

'smartSessionBI' is declared but its value is never read.
"function enableSessions((address,bytes,bytes32,(address,bytes)[],(string[],(address,bytes)[]),(bytes4,address,(address,bytes)[])[])[])"
])

const sessions: Session[] = [];

Check failure on line 116 in src/modules/validators/SmartSessionModule.ts

View workflow job for this annotation

GitHub Actions / size report

'sessions' is declared but its value is never read.

// const enableSessionsData = encodeFunctionData({
// abi: smartSessionBI,
// functionName: "enableSessions",
// args: [sessions]
// })
}



// Note:
// Needs more helpers to create a session struct. given constant validator, policies need to be built.
// Could be in helpers
// Todo:L
// Temp comment below

/*Session memory session = Session({
sessionValidator: ISessionValidator(address(yesSigner)),
salt: salt,
sessionValidatorInitData: "mockInitData",
userOpPolicies: _getEmptyPolicyDatas(address(yesPolicy)),
erc7739Policies: _getEmptyERC7739Data("mockContent", _getEmptyPolicyDatas(address(yesPolicy))), // optional and default empty
actions: _getEmptyActionDatas(_target, MockTarget.setValue.selector, address(yesPolicy)) // mocks. but usually one universal policy is enough
});*/
}

0 comments on commit e2fd99e

Please sign in to comment.