@@ -17,27 +17,6 @@ pub trait ProgramAccount {
1717 const DISCRIMINANT : <Self :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant ;
1818}
1919
20- fn validate_data_account < T > ( account : & DataAccount < T > , _syscalls : & impl SyscallCore ) -> Result < ( ) >
21- where
22- T : ProgramAccount + UnsizedType + ?Sized ,
23- {
24- if account. info . owner != & T :: OwnerProgram :: PROGRAM_ID {
25- bail ! ( ProgramError :: IllegalOwner ) ;
26- }
27-
28- let data = account. info . try_borrow_data ( ) ?;
29- if data. len ( ) < size_of :: < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > ( ) {
30- bail ! ( ProgramError :: InvalidAccountData ) ;
31- }
32- let discriminant: & <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant = from_bytes (
33- & data[ 0 ..size_of :: < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > ( ) ] ,
34- ) ;
35- if discriminant != & T :: DISCRIMINANT {
36- bail ! ( ProgramError :: InvalidAccountData ) ;
37- }
38- Ok ( ( ) )
39- }
40-
4120#[ derive( Debug , Derivative ) ]
4221#[ derivative( Copy ( bound = "" ) , Clone ( bound = "" ) ) ]
4322pub struct NormalizeRent < ' a , ' info , F > {
@@ -56,7 +35,15 @@ pub struct CloseAccount<'a, F> {
5635}
5736
5837#[ derive( AccountSet , Debug ) ]
59- #[ validate( extra_validation = validate_data_account( self , syscalls) ) ]
38+ #[ validate( extra_validation = self . validate( ) ) ]
39+ #[ validate(
40+ id = "address" ,
41+ arg = & Pubkey ,
42+ extra_validation = {
43+ anyhow:: ensure!( self . key( ) == arg) ;
44+ self . validate( )
45+ }
46+ ) ]
6047#[ cleanup( extra_cleanup = self . check_cleanup( syscalls) ) ]
6148#[ cleanup(
6249 id = "normalize_rent" ,
@@ -85,6 +72,17 @@ impl<'info, T> DataAccount<'info, T>
8572where
8673 T : ProgramAccount + UnsizedType + ?Sized ,
8774{
75+ /// Validates the owner and the discriminant of the account.
76+ fn validate ( & self ) -> Result < ( ) > {
77+ if self . info . owner != & T :: OwnerProgram :: PROGRAM_ID {
78+ bail ! ( ProgramError :: IllegalOwner ) ;
79+ }
80+ let data = self . info . try_borrow_data ( ) ?;
81+
82+ Self :: check_discriminant ( & data) ?;
83+ Ok ( ( ) )
84+ }
85+
8886 fn check_discriminant ( bytes : & [ u8 ] ) -> Result < ( ) > {
8987 if bytes. len ( ) < size_of :: < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > ( )
9088 || from_bytes :: < PackedValue < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > > (
@@ -123,7 +121,8 @@ where
123121 T :: from_bytes ( account_info_ref_mut) . map ( |ret| ret. ref_wrapper )
124122 }
125123
126- /// Closes the account
124+ /// Closes the account by zeroing the lamports and leaving the data as the
125+ /// [`StarFrameProgram::CLOSED_ACCOUNT_DISCRIMINANT`], reallocating down to size.
127126 pub fn close ( & mut self , recipient : & impl WritableAccount < ' info > ) -> Result < ( ) > {
128127 self . info . realloc (
129128 size_of :: < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > ( ) ,
@@ -137,8 +136,8 @@ where
137136 Ok ( ( ) )
138137 }
139138
140- /// Closes the account by reallocing and transfering. This is the same as calling `close` but
141- /// not abusable and harder for indexer detection.
139+ /// Closes the account by reallocating to zero and assigning to the System program.
140+ /// This is the same as calling `close` but not abusable and harder for indexer detection.
142141 pub fn close_full ( & mut self , recipient : & impl WritableAccount < ' info > ) -> Result < ( ) > {
143142 self . info . realloc (
144143 size_of :: < <T :: OwnerProgram as StarFrameProgram >:: AccountDiscriminant > ( ) ,
@@ -154,6 +153,7 @@ where
154153 Ok ( ( ) )
155154 }
156155
156+ /// See [`normalize_rent`]
157157 pub fn normalize_rent (
158158 & mut self ,
159159 funder : & ( impl WritableAccount < ' info > + SignedAccount < ' info > ) ,
@@ -163,6 +163,7 @@ where
163163 normalize_rent ( self . account_info ( ) , funder, system_program, syscalls)
164164 }
165165
166+ /// See [`refund_rent`]
166167 pub fn refund_rent (
167168 & mut self ,
168169 recipient : & impl WritableAccount < ' info > ,
@@ -171,34 +172,21 @@ where
171172 refund_rent ( self . account_info ( ) , recipient, sys_calls)
172173 }
173174
175+ /// Emits a warning message if the account has more lamports than required by rent.
174176 pub fn check_cleanup ( & self , sys_calls : & mut impl SyscallCore ) -> Result < ( ) > {
175177 #[ cfg( feature = "cleanup_rent_warning" ) ]
176178 {
177- use anyhow:: Context ;
178179 use std:: cmp:: Ordering ;
179180 if self . is_writable ( ) {
180181 let rent = sys_calls. get_rent ( ) ?;
181182 let lamports = self . account_info ( ) . lamports ( ) ;
182183 let data_len = self . account_info ( ) . data_len ( ) ;
183184 let rent_lamports = rent. minimum_balance ( data_len) ;
184- match rent_lamports. cmp ( & lamports) {
185- Ordering :: Greater => {
186- // is this more descriptive than just letting the runtime error out?
187- return Err ( anyhow:: anyhow!( ProgramError :: AccountNotRentExempt ) )
188- . with_context ( || {
189- format ! (
190- "{} was left with less lamports than required by rent" ,
191- self . key( )
192- )
193- } ) ;
194- }
195- Ordering :: Less => {
196- msg ! (
197- "{} was left with more lamports than required by rent" ,
198- self . key( )
199- ) ;
200- }
201- Ordering :: Equal => { }
185+ if rent_lamports. cmp ( & lamports) == Ordering :: Less {
186+ msg ! (
187+ "{} was left with more lamports than required by rent" ,
188+ self . key( )
189+ ) ;
202190 }
203191 }
204192 }
0 commit comments