Skip to content

Smart Contract Optimization via Custom Errors & Structural Refactoring Recducing String "requires"#102

Merged
DengreSarthak merged 5 commits intoStabilityNexus:mainfrom
aniket866:Refactor-and-optimize-contracts-by-custom-errors
Mar 23, 2026
Merged

Smart Contract Optimization via Custom Errors & Structural Refactoring Recducing String "requires"#102
DengreSarthak merged 5 commits intoStabilityNexus:mainfrom
aniket866:Refactor-and-optimize-contracts-by-custom-errors

Conversation

@aniket866
Copy link
Copy Markdown
Contributor

@aniket866 aniket866 commented Feb 1, 2026

Closes #103

What is one by this PR:

  • Refactored Chainvoice.sol to replace expensive string revert messages with gas-efficient Custom Errors across all functions.

  • Optimized contract modifiers and internal naming conventions to align with best practices and resolve linting warnings.

  • Updated Chainvoice.t.sol test suite to verify specific custom error selectors and cleaned up unused imports.

@kumawatkaran523 Please review

Summary by CodeRabbit

  • Refactor

    • Replaced ad-hoc revert messages with a unified set of explicit error types, tightening validation and standardizing failure handling across invoice creation, payments (single & batch), cancellations, withdrawals, treasury management and read operations.
  • Tests

    • Updated tests to assert the new error-driven reverts (error selectors) while preserving existing test logic and expectations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replaces string-based require checks in contracts/src/Chainvoice.sol with a comprehensive set of custom Solidity error types and switches reverts to use those errors across validation, invoice lifecycle, batch payments, view functions, and withdrawals; updates two tests to assert the new error selectors.

Changes

Cohort / File(s) Summary
Contract Error Handling Refactor
contracts/src/Chainvoice.sol
Adds many custom error declarations (e.g., Unauthorized, Reentrancy, ZeroAddress, SelfInvoicing, NotContract, InvalidToken, ArrayLengthMismatch, InvalidAmount, InvalidInvoiceId, NotInvoiceCreator, InvoiceNotCancellable, InvoiceAlreadyPaid, InvoiceCancelledError, IncorrectPaymentAmount, NativeTransferFailed, FeeMustBeNative, TokenTransferFailed, TreasuryNotSet, NoFeesAvailable, WithdrawFailed) and replaces string require checks with revert <Error>() across modifiers, invoice creation/cancellation/payment (including batch), view getters, and fee/treasury functions; formatting/comments adjusted.
Test Assertions Updated
contracts/test/Chainvoice.t.sol
Updates tests to expect custom error selectors (Chainvoice.NotAuthorizedPayer.selector, Chainvoice.IncorrectPaymentAmount.selector) instead of matching revert strings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • feat: Add two-step ownership transfer and admin events (#80) #81 — Overlapping edits to contracts/src/Chainvoice.sol, including custom errors and treasury validation changes.
  • #103 — Issue requesting replacement of string requires with custom errors across contracts; directly motivates these changes.
  • #102 — Prior proposed fix referenced in the linked issue; likely contains related refactor attempts.

Suggested labels

Solidity Lang, Linter

Poem

🐰 I hopped through code, swapped strings for names,
Errors now crisp, no costly flames.
Reverts sing true when inputs stray,
Invoices hop along their way.
🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: replacing string-based require statements with custom errors throughout the contract.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #103 by replacing all string-based require messages with custom Solidity errors throughout Chainvoice.sol and updating tests accordingly.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the objective of replacing string reverts with custom errors; no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
contracts/src/Chainvoice.sol (1)

107-123: ⚠️ Potential issue | 🟡 Minor

Inconsistent validation: amountDue is not validated for zero in single invoice creation.

createInvoicesBatch validates if (amt == 0) revert InvalidAmount() (line 176), but createInvoice allows zero-value invoices. This inconsistency could lead to unnecessary storage consumption and confusing user experience.

🛡️ Proposed fix to add zero-amount validation
 function createInvoice(
     address to,
     uint256 amountDue,
     address tokenAddress,
     string memory encryptedInvoiceData,
     string memory encryptedHash
 ) external {
     if (to == address(0)) revert ZeroAddress();
     if (to == msg.sender) revert SelfInvoicing();
+    if (amountDue == 0) revert InvalidAmount();

     if (tokenAddress != address(0)) {
🧹 Nitpick comments (4)
contracts/src/Chainvoice.sol (3)

52-54: Minor formatting issue: inline comment placement.

The trailing comment for encryptedHash is awkwardly placed on a separate line. Consider moving it inline.

✨ Suggested formatting fix
-        string encryptedHash;
-        // Content hash or integrity ref
+        string encryptedHash; // Content hash or integrity ref
     }

162-168: Minor: extra leading space at line 163.

There's an extra space before the if statement on line 163, causing inconsistent indentation.

✨ Formatting fix
         if (tokenAddress != address(0)) {
-             if (tokenAddress.code.length == 0) revert NotContract();
+            if (tokenAddress.code.length == 0) revert NotContract();
             (bool ok, ) = tokenAddress.staticcall(

267-274: Optional: First invoice is validated twice (here and again in the loop).

The validation at lines 271-274 for the first invoice (invoiceIds[0]) is repeated when i=0 in the loop at lines 279-290. This is correct but slightly gas-inefficient.

⛽ Consider starting loop at i=1 and including first invoice's amount
         InvoiceDetails storage inv0 = invoices[firstId];
         if (msg.sender != inv0.to) revert NotAuthorizedPayer();
         if (inv0.isPaid || inv0.isCancelled) revert AlreadySettled();
         address token = inv0.tokenAddress;
 
-        uint256 totalAmounts = 0;
+        uint256 totalAmounts = inv0.amountDue;
         uint256 totalNativeFee = fee * n;
         // Validate and sum
-        for (uint256 i = 0; i < n; i++) {
+        for (uint256 i = 1; i < n; i++) {
contracts/test/Chainvoice.t.sol (1)

95-115: Consider expanding test coverage for new custom errors.

Only NotAuthorizedPayer and IncorrectPaymentAmount are tested. Many new error paths are untested:

  • ZeroAddress, SelfInvoicing (in createInvoice)
  • InvalidInvoiceId, NotInvoiceCreator, InvoiceNotCancellable (in cancelInvoice)
  • InvoiceAlreadyPaid, InvoiceCancelledError (in payInvoice)
  • Batch-specific errors (ArrayLengthMismatch, InvalidAmount, MixedTokenBatch)

Would you like me to generate additional test cases covering these error paths?

@sach2004
Copy link
Copy Markdown
Contributor

sach2004 commented Mar 4, 2026

@DengreSarthak @kumawatkaran523 all the logic replacements look correct, inversions are done properly. also fixes the missing amountDue == 0 check in single createInvoice that batch already had. it is merge worthy

Comment thread contracts/src/Chainvoice.sol
@aniket866 aniket866 requested a review from DengreSarthak March 22, 2026 14:21
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
contracts/test/Chainvoice.t.sol (1)

99-125: ⚠️ Potential issue | 🟠 Major

The test migration is still incomplete.

These two assertions were updated, but Line 125 still expects the old "Only owner can call" string even though onlyOwner now reverts Unauthorized(). That leaves the suite out of sync with the contract, and the new selector-based failure paths added in createInvoice, cancelInvoice, batch pay, and withdrawFees are still untested.

Minimum fix for the stale ownership assertion
-        vm.expectRevert("Only owner can call");
+        vm.expectRevert(Chainvoice.Unauthorized.selector);
As per coding guidelines, "Verify that any modification to contract logic includes corresponding updates to automated tests", "Ensure failure paths and revert scenarios are explicitly handled and validated", and "Ensure security-sensitive logic changes are not introduced without adequate test coverage."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/test/Chainvoice.t.sol` around lines 99 - 125, Update the stale test
assertion in testInitiateOwnershipTransfer to expect the Unauthorized() selector
instead of the old "Only owner can call" string; locate the failing
vm.expectRevert call in testInitiateOwnershipTransfer and replace the string
expectation with Chainvoice.Unauthorized.selector (or the appropriate
Unauthorized selector symbol). Additionally, add or update tests to cover the
new selector-based revert paths introduced in createInvoice, cancelInvoice,
batch pay (batchPayInvoices or similar), and withdrawFees by using
vm.expectRevert(...selector) with the corresponding Chainvoice.* selector
symbols to validate those failure scenarios.
contracts/src/Chainvoice.sol (2)

343-372: ⚠️ Potential issue | 🟡 Minor

getPaymentStatus() overstates payability for ERC20 invoices.

In the token branch, canPay ignores the native fee that payInvoice() enforces with FeeMustBeNative(). A payer with enough tokens and allowance but 0 ETH still gets canPay == true, which will mislead any UI that relies on this helper.

Include the native fee in the ERC20 branch
             return (
-                bal >= invoice.amountDue && allw >= invoice.amountDue,
+                payer.balance >= fee && bal >= invoice.amountDue && allw >= invoice.amountDue,
                 bal,
                 allw
             );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/Chainvoice.sol` around lines 343 - 372, getPaymentStatus
currently reports canPay=true for ERC20 invoices without checking the native ETH
fee required by payInvoice (FeeMustBeNative), so update the token branch in
getPaymentStatus to also verify the payer's native balance covers fee: call
payer.balance >= fee and include that in the boolean alongside
IERC20(invoice.tokenAddress).balanceOf(payer) >= invoice.amountDue and
IERC20(...).allowance(payer, address(this)) >= invoice.amountDue; return the
same payer token balance and allowance as before but ensure canPay reflects both
token and native-fee checks for accurate UI signals.

290-301: ⚠️ Potential issue | 🟠 Major

Reject duplicate invoice IDs in a batch.

The validation loop checks every entry against current storage before any isPaid flag is flipped, so [id, id] passes, doubles totalAmounts/totalNativeFee, and pays the same invoice twice. With MAX_BATCH == 50, an O(n²) uniqueness check is cheap here.

Prevent duplicate IDs during validation
+    error DuplicateInvoiceId();
         for (uint256 i = 0; i < n; i++) {
             uint256 id = invoiceIds[i];
             if (id >= invoices.length) revert InvalidInvoiceId();
+            for (uint256 j = i + 1; j < n; j++) {
+                if (invoiceIds[j] == id) revert DuplicateInvoiceId();
+            }

             InvoiceDetails storage inv = invoices[id];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/Chainvoice.sol` around lines 290 - 301, The validation loop
must reject duplicate invoice IDs in the batch: before accumulating
totalAmounts/totalNativeFee, add a uniqueness check over invoiceIds (e.g. for
each i, loop j = i+1..n-1 and if invoiceIds[i] == invoiceIds[j] revert
DuplicateInvoiceId()) so duplicate ids like [id,id] fail; perform this check in
the same function where invoiceIds, invoices and InvoiceDetails storage inv are
validated (or introduce a DuplicateInvoiceId() error) and run it prior to
summing inv.amountDue and checking/setting inv.isPaid.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@contracts/src/Chainvoice.sol`:
- Around line 20-40: Replace the require string revert in setTreasuryAddress
with the new custom error: locate the setTreasuryAddress function and swap the
line that currently does require(newTreasury != address(0), "Zero address") to
instead revert with the ZeroAddress() custom error so the contract uses the new
error types consistently (reference: setTreasuryAddress and ZeroAddress()).
- Around line 128-133: The creation-time token probe must validate both
balanceOf and allowance to ensure future payments work: implement or extend the
helper _isERC20(address tokenAddress, address spender) to first verify
tokenAddress is a contract (tokenAddress.code.length > 0), then staticcall
balanceOf(address) and allowance(address,address) and ensure both calls succeed
and return >= 32 bytes; update createInvoice() and createInvoicesBatch() to call
_isERC20(tokenAddress, someSpender) (pass the contract or expected spender used
in payInvoice/payInvoicesBatch) instead of the current duplicated inline
balanceOf-only checks so invoices for non-ERC20-like tokens are rejected
up-front.

---

Outside diff comments:
In `@contracts/src/Chainvoice.sol`:
- Around line 343-372: getPaymentStatus currently reports canPay=true for ERC20
invoices without checking the native ETH fee required by payInvoice
(FeeMustBeNative), so update the token branch in getPaymentStatus to also verify
the payer's native balance covers fee: call payer.balance >= fee and include
that in the boolean alongside IERC20(invoice.tokenAddress).balanceOf(payer) >=
invoice.amountDue and IERC20(...).allowance(payer, address(this)) >=
invoice.amountDue; return the same payer token balance and allowance as before
but ensure canPay reflects both token and native-fee checks for accurate UI
signals.
- Around line 290-301: The validation loop must reject duplicate invoice IDs in
the batch: before accumulating totalAmounts/totalNativeFee, add a uniqueness
check over invoiceIds (e.g. for each i, loop j = i+1..n-1 and if invoiceIds[i]
== invoiceIds[j] revert DuplicateInvoiceId()) so duplicate ids like [id,id]
fail; perform this check in the same function where invoiceIds, invoices and
InvoiceDetails storage inv are validated (or introduce a DuplicateInvoiceId()
error) and run it prior to summing inv.amountDue and checking/setting
inv.isPaid.

In `@contracts/test/Chainvoice.t.sol`:
- Around line 99-125: Update the stale test assertion in
testInitiateOwnershipTransfer to expect the Unauthorized() selector instead of
the old "Only owner can call" string; locate the failing vm.expectRevert call in
testInitiateOwnershipTransfer and replace the string expectation with
Chainvoice.Unauthorized.selector (or the appropriate Unauthorized selector
symbol). Additionally, add or update tests to cover the new selector-based
revert paths introduced in createInvoice, cancelInvoice, batch pay
(batchPayInvoices or similar), and withdrawFees by using
vm.expectRevert(...selector) with the corresponding Chainvoice.* selector
symbols to validate those failure scenarios.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5b3eec8c-6f10-4693-9523-26f474a64bfa

📥 Commits

Reviewing files that changed from the base of the PR and between 072d4fd and e6c8b25.

📒 Files selected for processing (2)
  • contracts/src/Chainvoice.sol
  • contracts/test/Chainvoice.t.sol

Comment thread contracts/src/Chainvoice.sol
Comment thread contracts/src/Chainvoice.sol Outdated
@aniket866
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
contracts/src/Chainvoice.sol (2)

295-306: ⚠️ Potential issue | 🔴 Critical

Reject duplicate invoice IDs in payInvoicesBatch().

The settlement checks run before anything is marked paid, so [id, id] currently passes validation and charges the payer twice for the same invoice. That is an irreversible overpayment bug in both the native and ERC-20 branches. With MAX_BATCH capped at 50, a simple O(n²) duplicate precheck is cheap enough here.

Suggested fix
+    error DuplicateInvoiceId();
         for (uint256 i = 0; i < n; i++) {
             uint256 id = invoiceIds[i];
             if (id >= invoices.length) revert InvalidInvoiceId();
+            for (uint256 j = 0; j < i; j++) {
+                if (invoiceIds[j] == id) revert DuplicateInvoiceId();
+            }

             InvoiceDetails storage inv = invoices[id];

As per coding guidelines, "Review for common smart contract vulnerabilities, including but not limited to: Improper input validation."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/Chainvoice.sol` around lines 295 - 306, payInvoicesBatch
currently allows duplicate invoiceIds (e.g., [id,id]) which passes validation
and causes double payment; before performing settlement checks in
payInvoicesBatch iterate the invoiceIds once to detect duplicates (either with
an in-memory mapping(uint256=>bool) seen or an O(n^2) nested loop given
MAX_BATCH<=50) and revert on duplicates (e.g., DuplicateInvoiceId()) referencing
the invoiceIds array and InvoiceDetails entries; place this duplicate-precheck
at the start of payInvoicesBatch (before the loop that checks
inv.isPaid/isCancelled and accumulates totalAmounts) so no invoice can be
processed twice in the same batch.

356-377: ⚠️ Potential issue | 🟡 Minor

Make getPaymentStatus() match the actual payment preconditions.

canPay can still return true for an already-paid invoice, and the ERC-20 branch ignores the required native fee. That means off-chain callers can be told an invoice is payable even though payInvoice() will revert.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/Chainvoice.sol` around lines 356 - 377, getPaymentStatus
incorrectly reports invoices as payable when they're already paid and the ERC-20
branch ignores the native fee; update the function (the logic around
invoices[invoiceId], InvoiceDetails, payer, fee, and the IERC20
balanceOf/allowance checks) to first treat already-paid invoices as not payable
(e.g., check invoice.isPaid or invoice.amountPaid >= invoice.amountDue and
return canPay=false), and in the ERC-20 branch require both token
balance/allowance >= invoice.amountDue AND payer.balance >= fee (ensure the
native fee check is included) so canPay is true only when invoice not paid,
token funds/allowance cover amountDue, and the payer has native balance for the
fee.
♻️ Duplicate comments (1)
contracts/src/Chainvoice.sol (1)

178-184: ⚠️ Potential issue | 🟠 Major

Harden batch token validation to match the single-invoice path.

createInvoicesBatch() still accepts any contract that answers balanceOf(address), while createInvoice() now requires both balanceOf and allowance to succeed with valid return data. That inconsistency lets batch-created invoices slip through with tokens that later fail in payInvoicesBatch(), leaving invoices that cannot be settled. Please reuse the stricter probe here, ideally via a shared helper.

Suggested fix
         if (tokenAddress != address(0)) {
-             if (tokenAddress.code.length == 0) revert NotContract();
-            (bool ok, ) = tokenAddress.staticcall(
-                abi.encodeWithSignature("balanceOf(address)", address(this))
-            );
-            if (!ok) revert InvalidToken();
+            if (tokenAddress.code.length == 0) revert NotContract();
+            (bool balOk, bytes memory balData) = tokenAddress.staticcall(
+                abi.encodeWithSelector(IERC20.balanceOf.selector, address(this))
+            );
+            (bool allowanceOk, bytes memory allowanceData) = tokenAddress.staticcall(
+                abi.encodeWithSelector(IERC20.allowance.selector, address(this), address(this))
+            );
+            if (!balOk || balData.length < 32 || !allowanceOk || allowanceData.length < 32) {
+                revert InvalidToken();
+            }
         }

As per coding guidelines, "Ensure failure paths and revert scenarios are explicitly handled and validated."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/Chainvoice.sol` around lines 178 - 184, createInvoicesBatch
currently only probes token contracts with balanceOf, causing inconsistency with
createInvoice which probes both balanceOf and allowance; implement a shared
helper (e.g., _probeTokenContract(address tokenAddress)) and call it from both
createInvoice and createInvoicesBatch; in the helper ensure tokenAddress !=
address(0) and tokenAddress.code.length > 0, perform staticcall for both
"balanceOf(address)" and "allowance(address,address)", validate calls succeeded
and that returned data decodes to a uint256 for balance and allowance (revert
InvalidToken() on any failure), then reuse this helper in
payInvoicesBatch-related validation paths as appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@contracts/src/Chainvoice.sol`:
- Around line 295-306: payInvoicesBatch currently allows duplicate invoiceIds
(e.g., [id,id]) which passes validation and causes double payment; before
performing settlement checks in payInvoicesBatch iterate the invoiceIds once to
detect duplicates (either with an in-memory mapping(uint256=>bool) seen or an
O(n^2) nested loop given MAX_BATCH<=50) and revert on duplicates (e.g.,
DuplicateInvoiceId()) referencing the invoiceIds array and InvoiceDetails
entries; place this duplicate-precheck at the start of payInvoicesBatch (before
the loop that checks inv.isPaid/isCancelled and accumulates totalAmounts) so no
invoice can be processed twice in the same batch.
- Around line 356-377: getPaymentStatus incorrectly reports invoices as payable
when they're already paid and the ERC-20 branch ignores the native fee; update
the function (the logic around invoices[invoiceId], InvoiceDetails, payer, fee,
and the IERC20 balanceOf/allowance checks) to first treat already-paid invoices
as not payable (e.g., check invoice.isPaid or invoice.amountPaid >=
invoice.amountDue and return canPay=false), and in the ERC-20 branch require
both token balance/allowance >= invoice.amountDue AND payer.balance >= fee
(ensure the native fee check is included) so canPay is true only when invoice
not paid, token funds/allowance cover amountDue, and the payer has native
balance for the fee.

---

Duplicate comments:
In `@contracts/src/Chainvoice.sol`:
- Around line 178-184: createInvoicesBatch currently only probes token contracts
with balanceOf, causing inconsistency with createInvoice which probes both
balanceOf and allowance; implement a shared helper (e.g.,
_probeTokenContract(address tokenAddress)) and call it from both createInvoice
and createInvoicesBatch; in the helper ensure tokenAddress != address(0) and
tokenAddress.code.length > 0, perform staticcall for both "balanceOf(address)"
and "allowance(address,address)", validate calls succeeded and that returned
data decodes to a uint256 for balance and allowance (revert InvalidToken() on
any failure), then reuse this helper in payInvoicesBatch-related validation
paths as appropriate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6857459d-3635-4a2f-b3c9-d1235ed2238c

📥 Commits

Reviewing files that changed from the base of the PR and between e6c8b25 and 2013f9c.

📒 Files selected for processing (1)
  • contracts/src/Chainvoice.sol

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

@aniket866 Sure! Based on the explicit request and the human review from @sach2004 confirming the logic replacements are correct and the PR is merge worthy, I'm approving the PR. 🎉

✅ Actions performed

Comments resolved and changes approved.

@DengreSarthak DengreSarthak merged commit 3dcb4b3 into StabilityNexus:main Mar 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Contract refactor , Optimization and Using Custom Errors Where ever possible

3 participants