From a3ff297bba816453b89c5e3cb367e524653496b6 Mon Sep 17 00:00:00 2001 From: aniket866 Date: Sun, 1 Mar 2026 00:37:06 +0530 Subject: [PATCH] fixing-unbounded-loop --- contracts/src/Chainvoice.sol | 45 ++++++++++++++++++++++----- contracts/test/Chainvoice.t.sol | 10 ++++-- frontend/src/page/BatchPayment.jsx | 3 +- frontend/src/page/ReceivedInvoice.jsx | 3 +- frontend/src/page/SentInvoice.jsx | 3 +- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/contracts/src/Chainvoice.sol b/contracts/src/Chainvoice.sol index 38cb04cd..1ec37a13 100644 --- a/contracts/src/Chainvoice.sol +++ b/contracts/src/Chainvoice.sol @@ -351,19 +351,48 @@ contract Chainvoice { } } - function getSentInvoices(address user) external view returns (InvoiceDetails[] memory) { - return _getInvoices(sentInvoices[user]); +function getSentInvoices( + address user, + uint256 offset, + uint256 limit + ) external view returns (InvoiceDetails[] memory) { + return _getInvoicesPaginated(sentInvoices[user], offset, limit); } - function getReceivedInvoices(address user) external view returns (InvoiceDetails[] memory) { - return _getInvoices(receivedInvoices[user]); + function getReceivedInvoices( + address user, + uint256 offset, + uint256 limit + ) external view returns (InvoiceDetails[] memory) { + return _getInvoicesPaginated(receivedInvoices[user], offset, limit); } - function _getInvoices(uint256[] storage ids) internal view returns (InvoiceDetails[] memory) { - InvoiceDetails[] memory result = new InvoiceDetails[](ids.length); - for (uint256 i = 0; i < ids.length; i++) { - result[i] = invoices[ids[i]]; + function _getInvoicesPaginated( + uint256[] storage ids, + uint256 offset, + uint256 limit + ) internal view returns (InvoiceDetails[] memory) { + uint256 total = ids.length; + + // If the offset is beyond the array size, return an empty array + if (offset >= total) { + return new InvoiceDetails[](0); } + + // Calculate the actual limit (prevent out-of-bounds) + uint256 end = offset + limit; + if (end > total) { + end = total; + } + + uint256 size = end - offset; + InvoiceDetails[] memory result = new InvoiceDetails[](size); + + // Only loop through the requested chunk + for (uint256 i = 0; i < size; i++) { + result[i] = invoices[ids[offset + i]]; + } + return result; } diff --git a/contracts/test/Chainvoice.t.sol b/contracts/test/Chainvoice.t.sol index ecabfd5b..f4a70afb 100644 --- a/contracts/test/Chainvoice.t.sol +++ b/contracts/test/Chainvoice.t.sol @@ -18,7 +18,7 @@ contract ChainvoiceTest is Test { } /* ------------------------------------------------------------ */ - /* CREATE INVOICE */ + /* CREATE INVOICE */ /* ------------------------------------------------------------ */ function testCreateInvoice_Native() public { @@ -31,12 +31,16 @@ contract ChainvoiceTest is Test { "hash123" ); + // FIX: Added offset (0) and limit (10) for pagination Chainvoice.InvoiceDetails[] memory sent = chainvoice.getSentInvoices( - alice + alice, + 0, + 10 ); + // FIX: Added offset (0) and limit (10) for pagination Chainvoice.InvoiceDetails[] memory received = chainvoice - .getReceivedInvoices(bob); + .getReceivedInvoices(bob, 0, 10); assertEq(sent.length, 1); assertEq(received.length, 1); diff --git a/frontend/src/page/BatchPayment.jsx b/frontend/src/page/BatchPayment.jsx index 6982df09..71a5bc2e 100644 --- a/frontend/src/page/BatchPayment.jsx +++ b/frontend/src/page/BatchPayment.jsx @@ -359,7 +359,8 @@ function BatchPayment() { const contract = new Contract(contractAddress, ChainvoiceABI, signer); - const res = await contract.getReceivedInvoices(address); + // Fetching the first 100 invoices (Offset: 0, Limit: 100) +const res = await contract.getReceivedInvoices(address, 0, 100); if (!res || !Array.isArray(res) || res.length === 0) { setReceivedInvoices([]); diff --git a/frontend/src/page/ReceivedInvoice.jsx b/frontend/src/page/ReceivedInvoice.jsx index 1bac242f..cabac679 100644 --- a/frontend/src/page/ReceivedInvoice.jsx +++ b/frontend/src/page/ReceivedInvoice.jsx @@ -674,7 +674,8 @@ function ReceivedInvoice() { const contract = new Contract(contractAddress, ChainvoiceABI, signer); - const res = await contract.getReceivedInvoices(address); + // Fetching the first 100 invoices (Offset: 0, Limit: 100) +const res = await contract.getReceivedInvoices(address, 0, 100); if (!res || !Array.isArray(res) || res.length === 0) { setReceivedInvoice([]); diff --git a/frontend/src/page/SentInvoice.jsx b/frontend/src/page/SentInvoice.jsx index b953713f..c239b9a1 100644 --- a/frontend/src/page/SentInvoice.jsx +++ b/frontend/src/page/SentInvoice.jsx @@ -167,7 +167,8 @@ function SentInvoice() { const contract = new Contract(contractAddress, ChainvoiceABI, signer); - const res = await contract.getSentInvoices(address); + // Fetching the first 100 invoices (Offset: 0, Limit: 100) +const res = await contract.getSentInvoices(address, 0, 100); console.log("Raw invoices data:", res); if (!res || !Array.isArray(res) || res.length === 0) {