@@ -145,3 +145,162 @@ fn test_withdraw_insufficient_for_auctioneer_fee() {
145145
146146 assert ! ( matches!( result, Err ( VAppPanic :: InsufficientBalance { .. } ) ) ) ;
147147}
148+
149+ #[ test]
150+ fn test_withdraw_prover_self_withdraw ( ) {
151+ let mut test = setup ( ) ;
152+ let prover_address = test. fulfiller . address ( ) ;
153+ let prover_owner = test. requester . address ( ) ;
154+ let auctioneer = test. state . auctioneer ;
155+
156+ // Create a prover with owner different from prover address.
157+ let create_tx = create_prover_tx ( prover_address, prover_owner, U256 :: from ( 500 ) , 0 , 1 , 1 ) ;
158+ test. state . execute :: < MockVerifier > ( & create_tx) . unwrap ( ) ;
159+
160+ // Give the prover account some balance.
161+ let initial_balance = U256 :: from ( 200 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
162+ let prover_deposit = deposit_tx ( prover_address, initial_balance, 0 , 2 , 2 ) ;
163+ test. state . execute :: < MockVerifier > ( & prover_deposit) . unwrap ( ) ;
164+ assert_account_balance ( & mut test, prover_address, initial_balance) ;
165+
166+ // Give the prover owner balance to pay the withdraw fee.
167+ let owner_balance = U256 :: from ( 10 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
168+ let owner_deposit = deposit_tx ( prover_owner, owner_balance, 0 , 3 , 3 ) ;
169+ test. state . execute :: < MockVerifier > ( & owner_deposit) . unwrap ( ) ;
170+
171+ // Prover owner withdraws from prover account (prover pays amount, owner pays fee).
172+ let withdraw_amount = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
173+ let withdraw_tx = withdraw_tx ( & test. requester , prover_address, withdraw_amount, 0 ) ;
174+ let receipt = test. state . execute :: < MockVerifier > ( & withdraw_tx) . unwrap ( ) ;
175+
176+ // Verify amount was deducted from prover, fee from owner.
177+ let expected_prover_balance = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 200 - 100 = 100
178+ let expected_owner_balance = U256 :: from ( 9 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 10 - 1 = 9
179+ let auctioneer_fee = U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 1 PROVE
180+ assert_account_balance ( & mut test, prover_address, expected_prover_balance) ;
181+ assert_account_balance ( & mut test, prover_owner, expected_owner_balance) ;
182+ assert_account_balance ( & mut test, auctioneer, auctioneer_fee) ;
183+ assert_withdraw_receipt ( & receipt, prover_address, withdraw_amount) ;
184+ }
185+
186+ #[ test]
187+ fn test_withdraw_third_party_for_prover ( ) {
188+ let mut test = setup ( ) ;
189+ let prover_address = test. fulfiller . address ( ) ;
190+ let prover_owner = test. requester . address ( ) ;
191+ let third_party = test. signers [ 0 ] . clone ( ) ; // Third party who will sign the withdraw
192+ let auctioneer = test. state . auctioneer ;
193+
194+ // Create a prover with owner different from prover address.
195+ let create_tx = create_prover_tx ( prover_address, prover_owner, U256 :: from ( 500 ) , 0 , 1 , 1 ) ;
196+ test. state . execute :: < MockVerifier > ( & create_tx) . unwrap ( ) ;
197+
198+ // Give the prover account balance for withdrawal.
199+ let prover_balance = U256 :: from ( 150 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
200+ let prover_deposit = deposit_tx ( prover_address, prover_balance, 0 , 2 , 2 ) ;
201+ test. state . execute :: < MockVerifier > ( & prover_deposit) . unwrap ( ) ;
202+
203+ // Give the third party balance for fee payment.
204+ let third_party_balance = U256 :: from ( 10 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
205+ let third_party_deposit = deposit_tx ( third_party. address ( ) , third_party_balance, 0 , 3 , 3 ) ;
206+ test. state . execute :: < MockVerifier > ( & third_party_deposit) . unwrap ( ) ;
207+
208+ // Third party withdraws from prover account (account != signer).
209+ let withdraw_amount = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
210+ let withdraw_tx = withdraw_tx ( & third_party, prover_address, withdraw_amount, 0 ) ;
211+ let receipt = test. state . execute :: < MockVerifier > ( & withdraw_tx) . unwrap ( ) ;
212+
213+ // Verify amount was deducted from prover, fee from third party.
214+ let expected_prover_balance = U256 :: from ( 50 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 150 - 100 = 50
215+ let expected_third_party_balance = U256 :: from ( 9 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 10 - 1 = 9
216+ let auctioneer_fee = U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 1 PROVE
217+ assert_account_balance ( & mut test, prover_address, expected_prover_balance) ;
218+ assert_account_balance ( & mut test, third_party. address ( ) , expected_third_party_balance) ;
219+ assert_account_balance ( & mut test, auctioneer, auctioneer_fee) ;
220+ assert_withdraw_receipt ( & receipt, prover_address, withdraw_amount) ;
221+ }
222+
223+ #[ test]
224+ fn test_withdraw_third_party_insufficient_prover_balance ( ) {
225+ let mut test = setup ( ) ;
226+ let prover_address = test. fulfiller . address ( ) ;
227+ let prover_owner = test. requester . address ( ) ;
228+ let third_party = test. signers [ 0 ] . clone ( ) ;
229+
230+ // Create a prover.
231+ let create_tx = create_prover_tx ( prover_address, prover_owner, U256 :: from ( 500 ) , 0 , 1 , 1 ) ;
232+ test. state . execute :: < MockVerifier > ( & create_tx) . unwrap ( ) ;
233+
234+ // Give prover insufficient balance for withdrawal (only 50 PROVE).
235+ let prover_balance = U256 :: from ( 50 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
236+ let prover_deposit = deposit_tx ( prover_address, prover_balance, 0 , 2 , 2 ) ;
237+ test. state . execute :: < MockVerifier > ( & prover_deposit) . unwrap ( ) ;
238+
239+ // Give third party enough for fee.
240+ let third_party_balance = U256 :: from ( 10 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
241+ let third_party_deposit = deposit_tx ( third_party. address ( ) , third_party_balance, 0 , 3 , 3 ) ;
242+ test. state . execute :: < MockVerifier > ( & third_party_deposit) . unwrap ( ) ;
243+
244+ // Try to withdraw 100 PROVE from prover (should fail - prover has only 50).
245+ let withdraw_amount = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
246+ let withdraw_tx = withdraw_tx ( & third_party, prover_address, withdraw_amount, 0 ) ;
247+ let result = test. state . execute :: < MockVerifier > ( & withdraw_tx) ;
248+
249+ assert ! ( matches!( result, Err ( VAppPanic :: InsufficientBalance { account, amount, balance } )
250+ if account == prover_address && amount == withdraw_amount && balance == prover_balance) ) ;
251+ }
252+
253+ #[ test]
254+ fn test_withdraw_third_party_insufficient_fee_balance ( ) {
255+ let mut test = setup ( ) ;
256+ let prover_address = test. fulfiller . address ( ) ;
257+ let prover_owner = test. requester . address ( ) ;
258+ let third_party = test. signers [ 0 ] . clone ( ) ;
259+
260+ // Create a prover.
261+ let create_tx = create_prover_tx ( prover_address, prover_owner, U256 :: from ( 500 ) , 0 , 1 , 1 ) ;
262+ test. state . execute :: < MockVerifier > ( & create_tx) . unwrap ( ) ;
263+
264+ // Give prover enough balance for withdrawal.
265+ let prover_balance = U256 :: from ( 150 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
266+ let prover_deposit = deposit_tx ( prover_address, prover_balance, 0 , 2 , 2 ) ;
267+ test. state . execute :: < MockVerifier > ( & prover_deposit) . unwrap ( ) ;
268+
269+ // Give third party insufficient balance for fee (only 0.5 PROVE, need 1 PROVE).
270+ let third_party_balance = U256 :: from ( 5 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 17 ) ) ; // 0.5 PROVE
271+ let third_party_deposit = deposit_tx ( third_party. address ( ) , third_party_balance, 0 , 3 , 3 ) ;
272+ test. state . execute :: < MockVerifier > ( & third_party_deposit) . unwrap ( ) ;
273+
274+ // Try to withdraw from prover (should fail - third party can't pay fee).
275+ let withdraw_amount = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
276+ let auctioneer_fee = U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ; // 1 PROVE
277+ let withdraw_tx = withdraw_tx ( & third_party, prover_address, withdraw_amount, 0 ) ;
278+ let result = test. state . execute :: < MockVerifier > ( & withdraw_tx) ;
279+
280+ assert ! ( matches!( result, Err ( VAppPanic :: InsufficientBalance { account, amount, balance } )
281+ if account == third_party. address( ) && amount == auctioneer_fee && balance == third_party_balance) ) ;
282+ }
283+
284+ #[ test]
285+ fn test_withdraw_non_prover_only_self_can_withdraw ( ) {
286+ let mut test = setup ( ) ;
287+ let regular_account = test. requester . address ( ) ;
288+ let third_party = test. signers [ 0 ] . clone ( ) ;
289+
290+ // Give regular account some balance (no prover creation).
291+ let account_balance = U256 :: from ( 100 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
292+ let account_deposit = deposit_tx ( regular_account, account_balance, 0 , 1 , 1 ) ;
293+ test. state . execute :: < MockVerifier > ( & account_deposit) . unwrap ( ) ;
294+
295+ // Give third party enough for fee.
296+ let third_party_balance = U256 :: from ( 10 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
297+ let third_party_deposit = deposit_tx ( third_party. address ( ) , third_party_balance, 0 , 2 , 2 ) ;
298+ test. state . execute :: < MockVerifier > ( & third_party_deposit) . unwrap ( ) ;
299+
300+ // Try to have third party withdraw from regular account (should fail).
301+ let withdraw_amount = U256 :: from ( 50 ) * U256 :: from ( 10 ) . pow ( U256 :: from ( 18 ) ) ;
302+ let withdraw_tx = withdraw_tx ( & third_party, regular_account, withdraw_amount, 0 ) ;
303+ let result = test. state . execute :: < MockVerifier > ( & withdraw_tx) ;
304+
305+ assert ! ( matches!( result, Err ( VAppPanic :: OnlyAccountCanWithdraw ) ) ) ;
306+ }
0 commit comments