@@ -11,10 +11,13 @@ 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+ /// Stores forced action requests as (timestamp, status) by request_hash.
20+ forced_action_requests : Map <HashType , (Timestamp , RequestStatus )>,
1821 }
1922
2023 #[event]
@@ -48,17 +51,60 @@ pub(crate) mod RequestApprovalsComponent {
4851 public_key : PublicKey ,
4952 signature : Signature ,
5053 args : T ,
54+ ) -> HashType {
55+ let request_hash = self . store_approval (: public_key , : args );
56+ if let Option :: Some (owner_account ) = owner_account {
57+ assert (owner_account == get_caller_address (), errors :: CALLER_IS_NOT_OWNER_ACCOUNT );
58+ }
59+ validate_stark_signature (: public_key , msg_hash : request_hash , : signature );
60+ request_hash
61+ }
62+ /// Registers an approval for a request without signature or caller validation.
63+ ///
64+ /// This is intended for use with forced requests, where we track the same logical
65+ /// request in two maps:
66+ /// - `approved_requests` (generic approval status)
67+ /// - `forced_action_requests` (forced metadata: timestamp + status)
68+ /// This function is used to register the original request hash in the approvals map.
69+
70+ fn store_approval <T , + OffchainMessageHash <T >, + Drop <T >>(
71+ ref self : ComponentState <TContractState >, public_key : PublicKey , args : T ,
5172 ) -> HashType {
5273 let request_hash = args . get_message_hash (: public_key );
5374 assert (
5475 self . _get_request_status (: request_hash ) == RequestStatus :: NOT_REGISTERED ,
5576 errors :: REQUEST_ALREADY_REGISTERED ,
5677 );
78+ self . approved_requests. write (key : request_hash , value : RequestStatus :: PENDING );
79+ request_hash
80+ }
81+ /// Registers a forced approval action.
82+ /// If the owner_account is non-zero, the caller must be the owner_account.
83+ /// The request is signed with the public key.
84+ /// The request is stored with a status of PENDING, and the current time.
85+ fn register_forced_approval <T , + OffchainMessageHash <T >, + Drop <T >>(
86+ ref self : ComponentState <TContractState >,
87+ owner_account : Option <ContractAddress >,
88+ public_key : PublicKey ,
89+ signature : Signature ,
90+ args : T ,
91+ ) -> HashType {
92+ let request_hash = args . get_message_hash (: public_key );
93+
94+ assert (
95+ self
96+ . _get_forced_action_request_status (
97+ request_hash ,
98+ ) == RequestStatus :: NOT_REGISTERED ,
99+ errors :: REQUEST_ALREADY_REGISTERED ,
100+ );
57101 if let Option :: Some (owner_account ) = owner_account {
58102 assert (owner_account == get_caller_address (), errors :: CALLER_IS_NOT_OWNER_ACCOUNT );
59103 }
60104 validate_stark_signature (: public_key , msg_hash : request_hash , : signature );
61- self . approved_requests. write (key : request_hash , value : RequestStatus :: PENDING );
105+ self
106+ . forced_action_requests
107+ . write (key : request_hash , value : (Time :: now (), RequestStatus :: PENDING ));
62108 request_hash
63109 }
64110
@@ -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_action_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_action_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_action_request_status (
165+ self : @ ComponentState <TContractState >, request_hash : HashType ,
166+ ) -> RequestStatus {
167+ let (_ , status ) = self . forced_action_requests. read (request_hash );
168+ status
169+ }
94170 }
95171}
0 commit comments