@@ -11,10 +11,12 @@ pub(crate) mod RequestApprovalsComponent {
1111 use starkware_utils :: signature :: stark :: {
1212 HashType , PublicKey , Signature , validate_stark_signature,
1313 };
14+ use starkware_utils :: time :: time :: {Time , Timestamp };
1415
1516 #[storage]
1617 pub struct Storage {
1718 approved_requests : Map <HashType , RequestStatus >,
19+ forced_approved_requests : Map <HashType , (Timestamp , RequestStatus )>,
1820 }
1921
2022 #[event]
@@ -61,6 +63,50 @@ pub(crate) mod RequestApprovalsComponent {
6163 self . approved_requests. write (key : request_hash , value : RequestStatus :: PENDING );
6264 request_hash
6365 }
66+ /// Registers an approval for a request without signature or caller validation.
67+ ///
68+ /// This is intended for use with forced requests, which generate two distinct hashes:
69+ /// one for the original request and one for the forced request. The forced request hash
70+ /// is validated with signature and caller checks via `register_forced_approval`, while
71+ /// this function is used to register the original request hash in the approvals map.
72+ fn unsafe_register_approval <T , + OffchainMessageHash <T >, + Drop <T >>(
73+ ref self : ComponentState <TContractState >, public_key : PublicKey , args : T ,
74+ ) -> HashType {
75+ let request_hash = args . get_message_hash (: public_key );
76+ assert (
77+ self . _get_request_status (: request_hash ) == RequestStatus :: NOT_REGISTERED ,
78+ errors :: REQUEST_ALREADY_REGISTERED ,
79+ );
80+ self . approved_requests. write (key : request_hash , value : RequestStatus :: PENDING );
81+ request_hash
82+ }
83+ /// Registers a forced approval for a request.
84+ /// If the owner_account is non-zero, the caller must be the owner_account.
85+ /// The approval is signed with the public key.
86+ /// The signature is verified with the hash of the request.
87+ /// The request is stored with a status of PENDING, and the current time.
88+ fn register_forced_approval <T , + OffchainMessageHash <T >, + Drop <T >>(
89+ ref self : ComponentState <TContractState >,
90+ owner_account : Option <ContractAddress >,
91+ public_key : PublicKey ,
92+ signature : Signature ,
93+ args : T ,
94+ ) -> HashType {
95+ let request_hash = args . get_message_hash (: public_key );
96+
97+ assert (
98+ self . _get_forced_request_status (request_hash ) == RequestStatus :: NOT_REGISTERED ,
99+ errors :: REQUEST_ALREADY_REGISTERED ,
100+ );
101+ if let Option :: Some (owner_account ) = owner_account {
102+ assert (owner_account == get_caller_address (), errors :: CALLER_IS_NOT_OWNER_ACCOUNT );
103+ }
104+ validate_stark_signature (: public_key , msg_hash : request_hash , : signature );
105+ self
106+ . forced_approved_requests
107+ . write (key : request_hash , value : (Time :: now (), RequestStatus :: PENDING ));
108+ request_hash
109+ }
64110
65111 /// Consumes an approved request.
66112 /// Marks the request with status DONE.
@@ -80,6 +126,30 @@ pub(crate) mod RequestApprovalsComponent {
80126 self . approved_requests. write (request_hash , RequestStatus :: PROCESSED );
81127 request_hash
82128 }
129+
130+ /// Consumes a forced-approved request and updates its status to DONE.
131+ ///
132+ /// Validations:
133+ /// - The request must be in a PENDING state.
134+ ///
135+ /// Returns:
136+ /// - The timestamp of when the forced request was approved.
137+ /// - The hash of the forced request.
138+ fn consume_forced_approved_request <T , + OffchainMessageHash <T >, + Drop <T >>(
139+ ref self : ComponentState <TContractState >, args : T , public_key : PublicKey ,
140+ ) -> (Timestamp , HashType ) {
141+ let request_hash = args . get_message_hash (: public_key );
142+ let (request_time , request_status ) = self . forced_approved_requests. read (request_hash );
143+ match request_status {
144+ RequestStatus :: NOT_REGISTERED => panic_with_felt252 (errors :: REQUEST_NOT_REGISTERED ),
145+ RequestStatus :: PROCESSED => panic_with_felt252 (errors :: REQUEST_ALREADY_PROCESSED ),
146+ RequestStatus :: PENDING => {},
147+ }
148+ self
149+ . forced_approved_requests
150+ . write (request_hash , (request_time , RequestStatus :: PROCESSED ));
151+ (request_time , request_hash )
152+ }
83153 }
84154
85155 #[generate_trait]
@@ -91,5 +161,11 @@ pub(crate) mod RequestApprovalsComponent {
91161 ) -> RequestStatus {
92162 self . approved_requests. read (request_hash )
93163 }
164+ fn _get_forced_request_status (
165+ self : @ ComponentState <TContractState >, request_hash : HashType ,
166+ ) -> RequestStatus {
167+ let (_ , status ) = self . forced_approved_requests. read (request_hash );
168+ status
169+ }
94170 }
95171}
0 commit comments