@@ -63,7 +63,10 @@ import {
6363import { generatePrivateKey , privateKeyToAccount } from "viem/accounts" ;
6464import { multicall } from "viem/actions" ;
6565// Don't import this from "@quotes" alone, it is causing the circular dependency issue
66- import { SUPERTX_MEEUSEROP_STRUCT_TYPEHASH } from "../quotes/constants" ;
66+ import {
67+ SUPERTX_MEEUSEROP_STRUCT_TYPEHASH ,
68+ buildSessionSuperTxTypeHash ,
69+ } from "../quotes/constants" ;
6770import {
6871 type CustomOverride ,
6972 type EIP712DomainReturn ,
@@ -106,6 +109,7 @@ export class SimulationService {
106109 sessionDetails : GrantPermissionResponseType ;
107110 smartSessionMode : "ENABLE_AND_USE" | "USE" ;
108111 } ,
112+ rawUserOpHashes ?: Hex [ ] ,
109113 ) {
110114 // For trusted sponsorship, as we're ignoring the payment userOp, index should be sub by 1 to account for that
111115 // for all the userOps except the payment userOp itself
@@ -121,20 +125,29 @@ export class SimulationService {
121125 "0xcae0d1955b99d4832aef73ed0a2237045fad91a738ee5b96ba76b9a12ffc6f824ab2ecaeeeb903b50704fdf4a5d64216adf7d6aaaca0ed2a67b86d8525c4b4bb1c" as Hex ;
122126
123127 if ( sessionInfo ?. sessionDetails ) {
128+ // Smart sessions: use dynamic generic typehash with raw userOpHashes.
129+ // validateSignatureForOwner receives raw userOpHash from SmartSession,
130+ // so we must use raw hashes (not MeeUserOp EIP-712 hashes with timestamps).
131+ const sessionHashes = rawUserOpHashes
132+ ? ( isTrustedSponsorship ? rawUserOpHashes . slice ( 1 ) : rawUserOpHashes )
133+ : ( isTrustedSponsorship ? meeUserOpHashes . slice ( 1 ) : meeUserOpHashes ) ;
134+ const sessionTypeHash = rawUserOpHashes
135+ ? buildSessionSuperTxTypeHash ( sessionHashes . length )
136+ : SUPERTX_MEEUSEROP_STRUCT_TYPEHASH ;
137+
124138 const dummySignature = concatHex ( [
125139 "0x177eee00" , // Simple signature type
126140 encodeAbiParameters (
127141 [
128- { type : "bytes32" } , // stxStructTypeHash
142+ { type : "bytes32" } , // stxStructTypeHash (dynamic, session-specific)
129143 { type : "uint256" } , // userOp index
130- { type : "bytes32[]" } , // meeUserOpHashes - array of hashes
144+ { type : "bytes32[]" } , // raw userOpHashes
131145 { type : "bytes" } , // superTxSignature
132146 ] ,
133147 [
134- SUPERTX_MEEUSEROP_STRUCT_TYPEHASH ,
148+ sessionTypeHash ,
135149 BigInt ( index ) ,
136- // If it is a trusted sponsorship, the payment userop can be skipped because it is not going to be executed at all.
137- isTrustedSponsorship ? meeUserOpHashes . slice ( 1 ) : meeUserOpHashes ,
150+ sessionHashes ,
138151 dummyStxSig ,
139152 ] ,
140153 ) ,
@@ -537,6 +550,7 @@ export class SimulationService {
537550 const upperBoundTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 300 ; // 5 mins
538551
539552 const meeUserOpHashes : Hex [ ] = [ ] ;
553+ const rawUserOpHashes : Hex [ ] = [ ] ;
540554
541555 for ( const {
542556 packedUserOp,
@@ -558,6 +572,8 @@ export class SimulationService {
558572 { generateRandomHash : isTrustedPaymentUserOp } ,
559573 ) ;
560574
575+ rawUserOpHashes . push ( userOpHash ) ;
576+
561577 const meeUserOpHash = getMeeUserOpHashEip712 (
562578 userOpHash ,
563579 lowerBoundTimestamp ,
@@ -660,6 +676,7 @@ export class SimulationService {
660676 isTrustedSponsorship ,
661677 userOpIndex ,
662678 sessionDetails ? { sessionDetails, smartSessionMode } : undefined ,
679+ sessionDetails ? rawUserOpHashes : undefined ,
663680 ) ;
664681 }
665682
0 commit comments