Skip to content

Conversation

@rodrigopavezi
Copy link
Member

@rodrigopavezi rodrigopavezi commented Oct 21, 2025

  • Introduced Commerce Escrow payment types and parameters in the payment-types module.
  • Added Commerce Escrow wrapper to smart contracts and updated related scripts for deployment and verification.
  • Updated Docker Compose file to specify platform for services.
  • Added commerce-payments dependency in smart contracts package.

Summary by CodeRabbit

  • New Features

    • ERC‑20 commerce escrow wrapper with full authorize/charge/capture/void/reclaim/refund flows, public SDK types/exports, deployment task and helper scripts, test mocks and reentrancy tester.
  • Behavioral Changes

    • Recurring allowance flow simplified to a single approval transaction.
  • Tests

    • Extensive unit and integration tests covering encodings, transactions, edge cases, access control and reentrancy.
  • Infrastructure

    • Docker services now specify explicit platform (linux/amd64).
  • Chores

    • Added commerce‑payments dependency.

Fix #1650

…figurations

- Introduced Commerce Escrow payment types and parameters in the payment-types module.
- Added Commerce Escrow wrapper to smart contracts and updated related scripts for deployment and verification.
- Updated Docker Compose file to specify platform for services.
- Added commerce-payments dependency in smart contracts package.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 21, 2025

Walkthrough

Adds an ERC-20 Commerce Escrow Wrapper: new Solidity contracts (wrapper, interface, mock, reentrant tester), ABIs/artifacts, TypeScript types and payment-processor helpers/tests, create2/deploy tooling and scripts, package dependency, and Docker service platform keys.

Changes

Cohort / File(s) Summary
Docker Configuration
docker-compose.yml
Added platform: linux/amd64 to services: graph-node, ipfs, ganache, postgres, graph-deploy.
Types
packages/types/src/payment-types.ts
Added Commerce Escrow types: CommerceEscrowPaymentData, CommerceEscrowAuthorizeParams, CommerceEscrowCaptureParams, CommerceEscrowChargeParams, CommerceEscrowRefundParams, CommerceEscrowPaymentState.
Smart Contracts — Interface
packages/smart-contracts/src/contracts/interfaces/IAuthCaptureEscrow.sol
New IAuthCaptureEscrow interface with PaymentInfo struct and methods: getHash, authorize, capture, paymentState, void, charge, reclaim, refund.
Smart Contracts — Implementation
packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
New ERC20CommerceEscrowWrapper contract with constructor and external methods for authorize/capture/void/charge/reclaim/refund, storage/events, access control, SafeERC20 and reentrancy guards.
Smart Contracts — Mocks & Reentrancy Tester
packages/smart-contracts/src/contracts/test/MockAuthCaptureEscrow.sol, packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
Added mock MockAuthCaptureEscrow and MaliciousReentrant to simulate escrow behavior and reentrancy attacks for tests.
Smart Contracts — Solidity Tests
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
New extensive Hardhat test suite covering constructor, authorize/capture/void/charge/reclaim/refund flows, views, reentrancy and attack scenarios.
Artifacts — ABIs & Exports
packages/smart-contracts/src/lib/artifacts/.../0.1.0.json, .../index.ts, packages/smart-contracts/src/lib/artifacts/index.ts
Added ABIs and TypeScript artifact exports for ERC20CommerceEscrowWrapper and AuthCaptureEscrow; re-exported artifacts; included placeholder deployment entries.
Create2 / Deployment Tooling
packages/smart-contracts/scripts-create2/utils.ts, .../compute-one-address.ts, .../constructor-args.ts, .../verify.ts
Added ERC20CommerceEscrowWrapper to create2 deployment list and artifact resolver; added constructor-args and compute/verify handling.
Deployment Scripts & Hardhat
packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts, packages/smart-contracts/scripts/test-base-sepolia-deployment.ts, packages/smart-contracts/hardhat.config.ts
New deploy script, Base Sepolia helper, Hardhat task deploy-erc20-commerce-escrow-wrapper, network/explorer config additions, and solidity optimizer enabled.
Smart-Contracts Package Manifest
packages/smart-contracts/package.json
Added dependency commerce-payments via Git URL tag #v1.0.0.
Payment Processor — New Module & Export
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts, packages/payment-processor/src/index.ts
New module implementing wrapper address lookup, allowance helpers, encode helpers (authorize/capture/void/charge/reclaim/refund, set-allowance) and tx helpers; exported from package index.
Payment Processor Tests
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
Added unit tests for encoders, tx helpers, allowance handling, and error cases.
Recurring Allowance Simplification
packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts, packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
Removed isUSDT two-step approval logic; encodeSetRecurringAllowance now returns a single approve tx; tests updated accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant Payer
    participant Wrapper as ERC20CommerceEscrowWrapper
    participant Escrow as IAuthCaptureEscrow
    participant FeeProxy as ERC20FeeProxy
    participant Token as ERC20

    rect `#E6F0FF`
    Note over Payer,Wrapper: Authorization flow
    Payer->>Token: approve/transferFrom to Wrapper
    Wrapper->>Escrow: authorize(PaymentInfo, amount, tokenCollector, collectorData)
    Escrow-->>Wrapper: authorization recorded
    Wrapper-->>Wrapper: store PaymentData
    end

    rect `#E8FFE8`
    Note over Wrapper,FeeProxy: Capture (operator)
    Wrapper->>Escrow: capture(PaymentInfo, captureAmount, feeBps, feeReceiver)
    Escrow-->>Wrapper: capturable/refundable updated
    Wrapper->>FeeProxy: transferWithReferenceAndFee(token, merchant, merchantAmount, fee, feeReceiver, reference)
    FeeProxy->>Token: distribute(merchant, feeReceiver)
    end

    rect `#FFF2E6`
    Note over Wrapper,Escrow: Void / Reclaim / Refund
    alt Void
        Wrapper->>Escrow: void(PaymentInfo)
    else Reclaim
        Payer->>Wrapper: reclaimPayment(reference)
        Wrapper->>Escrow: reclaim(PaymentInfo)
    else Refund
        Wrapper->>Token: transferFrom(operator -> Wrapper, refundAmount)
        Wrapper->>Escrow: refund(PaymentInfo, refundAmount, tokenCollector, collectorData)
    end
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

Files/areas needing extra attention:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol — access control, reentrancy guards, SafeERC20 usage, fee math, event semantics.
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol and MockAuthCaptureEscrow — correctness of attack simulation and mock behaviors.
  • ABI/artifact files and index exports — ensure ABI matches Solidity and placeholder addresses are intentional.
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts — network artifact resolution, USDT edge cases, signer/provider interactions, and tx encoding.
  • create2 and deploy scripts — constructor args, verification steps, and network-specific addresses.

Possibly related PRs

Suggested reviewers

  • alexandre-abrioux
  • MantisClone
  • leoslr
  • bassgeta
  • kevindavee
  • aimensahnoun

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add Commerce Escrow payment functionality' is clear, specific, and accurately summarizes the main change of introducing Commerce Escrow payment features.
Description check ✅ Passed The pull request description provides a comprehensive overview of the changes, covering new payment types, smart contract updates, Docker Compose modifications, and dependency additions. Though the template is minimal, the description adequately addresses all significant modifications.
Linked Issues check ✅ Passed The PR successfully implements the Commerce Escrow wrapper smart contract functionality required by issue #1650, including new wrapper contract, payment types, deployment scripts, and comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the Commerce Escrow wrapper functionality. The Docker Compose platform changes and dependency updates support the main objective without introducing unrelated modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/checkout-contracts

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

…l parameters

- Refactored `encodeAuthorizePayment` and `encodeChargePayment` functions to pass individual parameters instead of a struct.
- Updated tests to reflect changes in parameter handling and added edge case scenarios for payment processing.
- Adjusted network configurations in tests to use the Sepolia testnet.
- Enhanced error handling for unsupported networks and invalid payment references in tests.
…s struct

- Updated `encodeAuthorizePayment` and `encodeChargePayment` functions to accept a single params struct instead of individual parameters.
- This change enhances code readability and maintainability by reducing parameter handling complexity.
…Interface

- Updated `encodeAuthorizePayment` and `encodeChargePayment` functions to utilize `utils.Interface` for encoding, allowing for individual parameters to be passed instead of a struct.
- This change improves compatibility with TypeScript and aligns with the ABI expectations for function calls.
@rodrigopavezi
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

✅ 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
Contributor

@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: 6

🧹 Nitpick comments (23)
docker-compose.yml (1)

4-4: Forcing linux/amd64 may slow Apple Silicon dev and CI runners; consider making it opt‑in.

Set via DOCKER_DEFAULT_PLATFORM or a compose profile/env override instead of hardcoding, and pin image tags (e.g., postgres:16) for reproducibility.

Have you validated these services on arm64 lately? If not, we can add a profile like profiles: ["amd64"] and document docker compose --profile amd64 up.

Also applies to: 26-26, 34-34, 47-47, 58-58

packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (8)

515-536: Validate feeBps and clear allowance after transfer to limit ERC20 allowance exposure.

  • Enforce feeBps <= 10_000.
  • After transferFromWithReferenceAndFee, reset allowance to 0.
   function _transferToMerchant(
@@
-    uint256 feeAmount = (amount * feeBps) / 10000;
+    if (feeBps > 10_000) revert InvalidFeeBps();
+    uint256 feeAmount = (amount * feeBps) / 10_000;
     uint256 merchantAmount = amount - feeAmount;
 
     IERC20(token).forceApprove(address(erc20FeeProxy), amount);
     erc20FeeProxy.transferFromWithReferenceAndFee(
@@
       feeReceiver
     );
+    // Clear residual allowance
+    IERC20(token).forceApprove(address(erc20FeeProxy), 0);

371-391: Also bound feeBps and clear allowance in capturePayment.

Mirror the same protections when capturing.

-    // Calculate fee amounts - ERC20FeeProxy will handle the split
-    uint256 feeAmount = (captureAmount * feeBps) / 10000;
+    if (feeBps > 10_000) revert InvalidFeeBps();
+    // Calculate fee amounts - ERC20FeeProxy will handle the split
+    uint256 feeAmount = (captureAmount * feeBps) / 10_000;
@@
     erc20FeeProxy.transferFromWithReferenceAndFee(
@@
     );
+    // Clear residual allowance
+    IERC20(payment.token).forceApprove(address(erc20FeeProxy), 0);

200-212: Add upstream validation: amount ≤ maxAmount to avoid wasted gas on escrow revert.

Escrow likely enforces this; checking here improves UX.

   function authorizePayment(AuthParams calldata params) external nonReentrant {
@@
-    // Create and execute authorization
+    if (params.amount > params.maxAmount) revert ScalarOverflow();
+    // Create and execute authorization

346-350: Avoid external self‑call; call internal logic directly to save gas.

Use _executeAuthorization(params) and keep validations in this function. Current pattern is safe but costs an extra call.


400-438: Mark payment inactive after a successful void to prevent redundant calls and save lookups.

This avoids later onlyOperator/state calls on a finalized payment.

     commerceEscrow.void(paymentInfo);
@@
     emit PaymentVoided(
@@
     );
+    payment.isActive = false;

538-576: Also mark payment inactive on reclaim.

Same reasoning as void.

     commerceEscrow.reclaim(paymentInfo);
@@
     emit PaymentReclaimed(
@@
     );
+    payment.isActive = false;

584-627: Clear temporary approval after refund; optionally validate refundAmount > 0.

Minimize allowance window; small input sanity check helps.

-    IERC20(payment.token).forceApprove(tokenCollector, refundAmount);
+    IERC20(payment.token).forceApprove(tokenCollector, refundAmount);
@@
     commerceEscrow.refund(paymentInfo, refundAmount, tokenCollector, collectorData);
+    // Clear residual allowance
+    IERC20(payment.token).forceApprove(tokenCollector, 0);

173-184: Use a dedicated error for payer checks to improve debuggability.

Reusing InvalidOperator is confusing.

-    if (msg.sender != payment.payer) {
-      revert InvalidOperator(msg.sender, payment.payer); // Reusing the same error for simplicity
-    }
+    if (msg.sender != payment.payer) {
+      revert InvalidPayer(msg.sender, payment.payer);
+    }

Add:

 error ZeroAddress();
+error InvalidPayer(address sender, address expectedPayer);
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (4)

43-48: Stabilize time-dependent tests

Avoid Date.now()/provider time drift. Use Hardhat time helpers to set block timestamps deterministically before calling state-changing functions. Example: setNextBlockTimestamp + mine.

Apply Hardhat helpers in beforeEach where expiries are computed to prevent flaky behavior across environments.

Also applies to: 1012-1032


435-447: Confirm event emitter (wrapper vs ERC20FeeProxy)

Assertions expect TransferWithReferenceAndFee to be emitted by wrapper. If the event originates from ERC20FeeProxy, target that contract instead or have the wrapper re-emit. Please verify actual emitter to avoid false negatives.

Also applies to: 545-557


341-353: Tighten revert assertions

Use revertedWith/ to pin failure reason (e.g., non-operator, over-capture, nonexistent payment). This reduces accidental passes due to unrelated reverts.

Also applies to: 461-486, 659-662


767-787: “Reentrancy Protection” tests don’t verify nonReentrant

These tests only execute happy paths. If the goal is to assert the guard exists, check for the modifier via ABI or attempt a crafted reentrant call using a malicious token/mock. Otherwise, rename the describe block to reflect intent.

Also applies to: 789-833

packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (4)

75-103: Decouple from concrete deployment addresses

Tests expect '0x123…' for sepolia/goerli/mumbai without mocking the source of truth. Stub the artifact getter or spy on getCommerceEscrowWrapperAddress to return deterministic values, or assert “is valid address” rather than equality.


81-92: Relax brittle error string matches

Multiple tests assert an exact message. Prefer regex (toThrow(/No deployment for network/)) or inline snapshots to avoid breakage from punctuation/wording changes while still validating semantics.

Also applies to: 252-262, 367-375, 818-826


265-297: Nice mocking pattern; minor isolation tweak

The jest.doMock + resetModules flow is good. Consider jest.isolateModules for tighter scoping and to avoid cross-test cache bleed if this file grows.


768-805: Gas price edge-cases: add explicit expectations

You already mock gasPrice extremes. Consider also asserting sendTransaction call args include or omit gas parameters per your helpers’ behavior to catch accidental overrides.

packages/smart-contracts/src/contracts/test/MockAuthCaptureEscrow.sol (3)

5-6: Use SafeERC20 for robust token interactions

transfer/transferFrom return values are ignored; some tokens don’t revert on failure. Even for mocks, using SafeERC20 prevents silent failures and aligns with OZ best practices.

Apply SafeERC20 and replace calls with safeTransfer/safeTransferFrom.

Also applies to: 39-41, 66-71, 98-103, 117-125, 139-145, 159-167


15-17: Guard against uint120 downcast truncation

Explicit casts from uint256 to uint120 can silently truncate. Add bounds checks (require(amount <= type(uint120).max, ...)) before casting or keep state as uint256 in the mock to avoid surprises in edge-case tests.

Also applies to: 45-47, 69-71, 97-103, 121-125, 164-165


43-47: Authorize sets hasCollectedPayment=true

Semantically “collected” often means captured to receiver. If this flag is intended to mean “funds held in escrow,” rename or document it. Otherwise set false on authorize and true only after capture/charge. Confirm expectations with wrapper tests.

packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (3)

521-534: Avoid unsafe BigNumber → number conversions for timestamps

toNumber() can overflow for large values. Either:

  • return strings/BigNumbers for time fields, or
  • add a safe guard before converting (throw if > Number.MAX_SAFE_INTEGER).

Would you like a small helper (toSafeNumber) and type update to prevent silent precision loss?


299-323: DRY the transaction helpers

sendTransaction boilerplate is duplicated. Extract a tiny sendToWrapper(network, signer, data) to reduce repetition and centralize future gas/nonce tweaks.

Also applies to: 334-358, 369-393, 404-428, 439-463, 474-498


71-104: USDT approve reset: consider making it token-behavior driven

You require callers to pass isUSDT. Optionally detect non-standard approve behavior by token address (lookup) or expose a helper isUsdtLike(tokenAddress) in the payment-processor to avoid misconfiguration by integrators.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a40ae6 and 3afacad.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (17)
  • docker-compose.yml (4 hunks)
  • packages/payment-processor/src/index.ts (1 hunks)
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1 hunks)
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (1 hunks)
  • packages/smart-contracts/package.json (1 hunks)
  • packages/smart-contracts/scripts-create2/compute-one-address.ts (1 hunks)
  • packages/smart-contracts/scripts-create2/constructor-args.ts (1 hunks)
  • packages/smart-contracts/scripts-create2/utils.ts (2 hunks)
  • packages/smart-contracts/scripts-create2/verify.ts (1 hunks)
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1 hunks)
  • packages/smart-contracts/src/contracts/interfaces/IAuthCaptureEscrow.sol (1 hunks)
  • packages/smart-contracts/src/contracts/test/MockAuthCaptureEscrow.sol (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/0.1.0.json (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/index.ts (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/index.ts (1 hunks)
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1 hunks)
  • packages/types/src/payment-types.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-06T14:48:18.698Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1484
File: packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts:0-0
Timestamp: 2024-11-06T14:48:18.698Z
Learning: In `packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts`, when the existing happy path tests are deemed sufficient, additional test cases may not be necessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
🔇 Additional comments (9)
packages/smart-contracts/src/contracts/interfaces/IAuthCaptureEscrow.sol (1)

1-79: LGTM — clear interface and tight types.

The struct packing (uint120/uint48) is good for gas; function set matches wrapper usage.

packages/payment-processor/src/index.ts (1)

33-33: Build configuration will correctly emit dist/payment/erc20-commerce-escrow-wrapper.js(.d.ts) — no issues found.

Verification confirms:

  • Source file exists with proper exports
  • Re-export statement correctly placed in index.ts line 33
  • tsconfig.build.json configured with outDir="dist" and rootDir="src", ensuring individual module files are emitted
  • Tree-shaking preserved via export * statement

The build will automatically create the expected dist artifacts on standard TypeScript compilation.

packages/smart-contracts/scripts-create2/verify.ts (1)

54-55: LGTM! Verification integration is consistent with existing contracts.

The addition of both ERC20RecurringPaymentProxy and ERC20CommerceEscrowWrapper cases follows the established pattern and correctly reuses the shared verification logic.

packages/smart-contracts/src/lib/artifacts/index.ts (1)

19-19: LGTM! Export follows existing pattern.

The export statement is correctly placed and maintains consistency with other artifact exports.

packages/smart-contracts/scripts-create2/compute-one-address.ts (1)

69-70: LGTM! Address computation integration is correct.

The new cases properly integrate with the existing CREATE2 address computation flow.

packages/smart-contracts/scripts-create2/utils.ts (2)

25-25: LGTM! Deployment list updated correctly.


66-67: LGTM! Artifact resolution follows established pattern.

packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/0.1.0.json (1)

1-853: LGTM! ABI definition is comprehensive and well-structured.

The ABI correctly defines:

  • Constructor parameters for commerce escrow and fee proxy dependencies
  • Custom error types for validation failures
  • Events covering the full authorize/capture/void/refund lifecycle
  • Public functions for payment operations and state queries
  • PaymentData struct matching the TypeScript type definitions
packages/types/src/payment-types.ts (1)

416-486: LGTM! Type definitions correctly model the Commerce Escrow contract interface.

The new interfaces provide comprehensive type safety for:

  • Payment data structure matching the on-chain PaymentData struct
  • Authorization parameters with expiry timestamps and collector configuration
  • Capture parameters with fee calculation (basis points)
  • Charge parameters appropriately extending authorization with capture fees
  • Refund parameters with collector data
  • Payment state queries

Field types appropriately use BigNumberish for amounts and number for timestamps and BPS values.

Comment on lines +7 to +42
export const erc20CommerceEscrowWrapperArtifact = new ContractArtifact<ERC20CommerceEscrowWrapper>(
{
'0.1.0': {
abi: ABI_0_1_0,
deployment: {
private: {
address: '0x0000000000000000000000000000000000000000', // Placeholder - to be updated with actual deployment
creationBlockNumber: 0,
},
// Testnet deployments for testing
sepolia: {
address: '0x1234567890123456789012345678901234567890', // Placeholder - to be updated with actual deployment
creationBlockNumber: 0,
},
goerli: {
address: '0x1234567890123456789012345678901234567890', // Placeholder - to be updated with actual deployment
creationBlockNumber: 0,
},
mumbai: {
address: '0x1234567890123456789012345678901234567890', // Placeholder - to be updated with actual deployment
creationBlockNumber: 0,
},
// TODO: Add deployment addresses for mainnet networks once deployed
// mainnet: {
// address: '0x0000000000000000000000000000000000000000',
// creationBlockNumber: 0,
// },
// matic: {
// address: '0x0000000000000000000000000000000000000000',
// creationBlockNumber: 0,
// },
},
},
},
'0.1.0',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

All deployment addresses are placeholders and must be updated.

The artifact contains placeholder addresses for all networks:

  • Private network: zero address (0x000...000)
  • Testnets (Sepolia, Goerli, Mumbai): invalid placeholder (0x123...890)
  • Mainnet networks: commented out

Additionally, all creationBlockNumber values are set to 0, which should be updated to the actual deployment block numbers for event indexing and proper initialization.

Before moving out of draft:

  1. Deploy the contract to each target network
  2. Update all addresses with actual deployment addresses
  3. Set correct creation block numbers
  4. Uncomment and populate mainnet deployment sections if targeting production networks
🤖 Prompt for AI Agents
In
packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/index.ts
around lines 7 to 42, the artifact uses placeholder addresses and zero
creationBlockNumber values for all networks; replace each placeholder address
with the actual deployed contract address for the target network and set
creationBlockNumber to the block number where that contract was deployed (for
private, sepolia, goerli, mumbai and any mainnet networks you intend to
support), and if deploying to mainnet uncomment and populate the mainnet/matic
sections accordingly so event indexing and initialization use real deployment
metadata.

… escrow address

- Enhanced error messaging in `getCommerceEscrowWrapperAddress` for better clarity on network deployments.
- Updated the placeholder commerce escrow address in `constructor-args.ts` to the actual deployed AuthCaptureEscrow address.
- Added new `ScalarOverflow` error to `ERC20CommerceEscrowWrapper` for better overflow handling in payment parameters.
- Adjusted payment processing logic to ensure no fees are taken at escrow, aligning with ERC20FeeProxy for compatibility.
…sts and event assertions

- Added comprehensive tests for encoding functions in `erc20-commerce-escrow-wrapper` to verify function selectors and parameter inclusion.
- Improved event assertions in `ERC20CommerceEscrowWrapper` tests to check emitted events with exact values for payment authorization, capture, voiding, charging, and reclaiming payments.
- Validated function signatures and parameter types across various payment functions to ensure expected behavior.
@rodrigopavezi
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 24, 2025

✅ 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
Contributor

@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

🧹 Nitpick comments (1)
packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1)

178-187: Consider dedicated error for payer validation.

The onlyPayer modifier reuses InvalidOperator error, which could confuse debugging. A dedicated InvalidPayer error would improve clarity.

Apply this diff if desired:

   /// @notice Invalid operator for this payment
   error InvalidOperator(address sender, address expectedOperator);

+  /// @notice Invalid payer for this payment
+  error InvalidPayer(address sender, address expectedPayer);
   modifier onlyPayer(bytes8 paymentReference) {
     PaymentData storage payment = payments[paymentReference];
     if (!payment.isActive) revert PaymentNotFound();

     // Check if the caller is the payer for this payment
     if (msg.sender != payment.payer) {
-      revert InvalidOperator(msg.sender, payment.payer); // Reusing the same error for simplicity
+      revert InvalidPayer(msg.sender, payment.payer);
     }
     _;
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3afacad and 924f7f4.

📒 Files selected for processing (6)
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1 hunks)
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (1 hunks)
  • packages/smart-contracts/package.json (1 hunks)
  • packages/smart-contracts/scripts-create2/constructor-args.ts (1 hunks)
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1 hunks)
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/smart-contracts/package.json
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (14)
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (4)

1-90: LGTM: Well-structured test setup.

The test scaffolding properly deploys all contracts (TestERC20, ERC20FeeProxy, MockAuthCaptureEscrow, ERC20CommerceEscrowWrapper), allocates tokens, and sets up test participants. The unique payment reference generator is a good pattern for avoiding collisions across tests.


238-276: Verify that wrapper delegates validation to the escrow contract.

Tests confirm the wrapper doesn't validate amount vs maxAmount relationships or expiry timestamp ordering. This suggests validation is delegated to the underlying commerceEscrow contract.

Please confirm this is the intended design - that the wrapper trusts the escrow to enforce business rules while focusing on authorization, fee handling, and Request Network integration.


635-672: LGTM: Refund testing appropriately scoped.

The test suite correctly focuses on access control for refunds at the unit level, with the comment noting that full refund flow testing requires integration tests with real contracts. This is a reasonable testing strategy given the complexity of the operator token pull flow.


906-1129: Excellent security test coverage.

The attack vector tests comprehensively cover front-running protection, access control enforcement, overflow/underflow scenarios, and boundary conditions. This demonstrates a security-first testing approach.

packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (4)

22-30: LGTM: Error message properly aligned.

The error message now matches the expected format from tests and other call sites as requested in the previous review.


71-104: LGTM: Proper USDT allowance handling.

The function correctly implements the USDT quirk by resetting allowance to zero before setting a new value. This prevents the well-known USDT approval race condition issue.


115-146: Acceptable workaround for TypeScript interface limitations.

The manual parameter encoding using utils.Interface and individual parameter passing avoids TypeScript struct mapping issues. While not ideal, this is a pragmatic solution that maintains type safety at the boundaries.


509-535: LGTM: Proper type conversions for consumer ergonomics.

The function correctly converts BigNumber fields to more ergonomic JavaScript types, making the returned data easier to work with in TypeScript consumers.

packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (6)

270-300: LGTM: Overflow checks properly implemented.

The explicit bounds checks before casting to smaller uint types (uint120, uint48) address the previous review concern about silent numeric truncation. This prevents large inputs from being truncated before hashing/authorizing.


469-526: LGTM: Double fee issue resolved.

The charge flow now correctly applies fees only once via ERC20FeeProxy, passing zero fee parameters to commerceEscrow.charge. This addresses the previous critical review concern about double fee application.


370-411: LGTM: Secure capture implementation with proper fee handling.

The capture flow correctly:

  • Enforces operator-only access
  • Retrieves full amount from escrow without fees
  • Delegates fee splitting to ERC20FeeProxy for Request Network event compatibility
  • Uses forceApprove for USDT-like token compatibility

415-589: LGTM: Void and reclaim flows properly delegated.

Both functions correctly:

  • Enforce appropriate access control (operator for void, payer for reclaim)
  • Query state before the operation
  • Delegate actual token transfers to the escrow contract
  • Emit Request Network-compatible events for integration

596-640: LGTM: Refund flow handles multi-party token movement correctly.

The refund implementation properly orchestrates the token flow from the operator through the wrapper to the collector and ultimately to the payer, with appropriate approvals at each step.


642-689: LGTM: Clean view function implementations.

The query functions appropriately check payment existence and delegate state queries to the underlying escrow contract. The capability checks (canCapture, canVoid) provide useful consumer utilities.

…wWrapper tests

- Improved event assertions for payment authorization, capture, voiding, charging, and reclaiming payments to verify emitted events with exact values.
- Updated tests to utilize transaction receipts for event validation, ensuring accurate checks for emitted event arguments.
- Removed unnecessary assertions for parameters not stored in the PaymentData struct.
…Wrapper tests

- Replaced direct event assertions with `expect(tx).to.emit` for `CaptureCalled` and `ChargeCalled` events to enhance clarity and maintainability.
- Removed redundant checks for event parameters that are already validated through transaction receipts.
@rodrigopavezi rodrigopavezi marked this pull request as ready for review October 24, 2025 13:33
Copy link
Contributor

@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: 1

🧹 Nitpick comments (5)
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (5)

44-47: Consider using blockchain timestamp for time constants.

The time constants use Date.now() which captures JavaScript execution time rather than blockchain time. For more accurate testing, consider obtaining the current block timestamp from the provider. While this may not affect the current tests if the wrapper doesn't validate expiry times, it's a best practice for time-dependent smart contract testing.

Apply this diff to use blockchain time:

-  // Time constants
-  const currentTime = Math.floor(Date.now() / 1000);
-  const preApprovalExpiry = currentTime + 3600; // 1 hour
-  const authorizationExpiry = currentTime + 7200; // 2 hours
-  const refundExpiry = currentTime + 86400; // 24 hours
+  // Time constants - will be set in before hook
+  let currentTime: number;
+  let preApprovalExpiry: number;
+  let authorizationExpiry: number;
+  let refundExpiry: number;

Then in the before hook after deploying contracts:

  // Get current blockchain time
  const currentBlock = await ethers.provider.getBlock('latest');
  currentTime = currentBlock.timestamp;
  preApprovalExpiry = currentTime + 3600; // 1 hour
  authorizationExpiry = currentTime + 7200; // 2 hours
  refundExpiry = currentTime + 86400; // 24 hours

415-432: Consider verifying remaining capturable amount in partial capture test.

The partial capture test successfully verifies that multiple captures can be performed, but doesn't check the remaining capturable amount after each operation. Consider adding state verification to ensure the capturable amount decreases correctly.

Based on learnings

Add state verification:

     // First partial capture
     await expect(
       wrapper
         .connect(operator)
         .capturePayment(authParams.paymentReference, firstCapture, feeBps, feeReceiverAddress),
     ).to.emit(wrapper, 'PaymentCaptured');
+
+    // Verify remaining capturable amount
+    let [hasCollected, capturable, refundable] = await wrapper.getPaymentState(
+      authParams.paymentReference,
+    );
+    expect(capturable).to.equal(amount.sub(firstCapture));

     // Second partial capture
     await expect(
       wrapper
         .connect(operator)
         .capturePayment(authParams.paymentReference, secondCapture, feeBps, feeReceiverAddress),
     ).to.emit(wrapper, 'PaymentCaptured');
+
+    // Verify final capturable amount
+    [hasCollected, capturable, refundable] = await wrapper.getPaymentState(
+      authParams.paymentReference,
+    );
+    expect(capturable).to.equal(amount.sub(firstCapture).sub(secondCapture));

519-564: Charge functionality has minimal test coverage.

The charge tests only cover the happy path and invalid reference scenarios. Consider adding tests for:

  • Access control (who can call chargePayment)
  • Edge cases (zero amounts, fee calculations, etc.)
  • State verification after charging

If charge is a critical payment path, more comprehensive testing would improve confidence.


566-612: Reclaim tests cover core functionality.

The reclaim tests verify the happy path (payer can reclaim their authorized payment) and access control (non-payers cannot reclaim). Consider adding edge case tests for reclaim after partial/full capture if this is a critical flow.


1017-1038: Gas limit test doesn't verify gas consumption.

The test is titled "Gas Limit Edge Cases" but only verifies that large collector data is accepted, not that it stays within gas limits. Consider either:

  1. Measuring actual gas consumption and asserting it's reasonable, OR
  2. Renaming to "Large Collector Data Handling"

To measure gas:

   it('should handle large collector data', async () => {
     const largeData = '0x' + 'ff'.repeat(1000); // 1000 bytes of data

     const authParams = {
       paymentReference: getUniquePaymentReference(),
       payer: payerAddress,
       merchant: merchantAddress,
       operator: operatorAddress,
       token: testERC20.address,
       amount,
       maxAmount,
       preApprovalExpiry,
       authorizationExpiry,
       refundExpiry,
       tokenCollector: tokenCollectorAddress,
       collectorData: largeData,
     };

-    await expect(wrapper.authorizePayment(authParams)).to.emit(wrapper, 'PaymentAuthorized');
+    const tx = await wrapper.authorizePayment(authParams);
+    const receipt = await tx.wait();
+    expect(receipt.gasUsed).to.be.lt(5000000); // Assert reasonable gas limit
+    await expect(tx).to.emit(wrapper, 'PaymentAuthorized');
   });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 924f7f4 and 8cc4dac.

📒 Files selected for processing (1)
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
🔇 Additional comments (8)
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (8)

91-123: LGTM! Comprehensive constructor validation tests.

The constructor tests effectively cover initialization with valid addresses and zero address validation for both parameters. The tests ensure the contract properly validates its dependencies during deployment.


436-517: LGTM! Comprehensive void functionality tests.

The void tests effectively cover the happy path, access control, and important edge cases including voiding after capture and double void attempts. The tests verify proper token return to the payer with no fees.


653-754: LGTM! Comprehensive view function tests.

The view function tests thoroughly cover all getter methods with both valid and invalid payment references, including edge cases and state transitions. The tests properly verify the contract's read-only interface.


756-814: Edge case tests cover key scenarios.

The edge case tests verify handling of zero amounts, large amounts, and empty collector data. Combined with the boundary value tests later in the file, this provides good coverage of edge conditions.


885-964: LGTM! Comprehensive security-focused tests.

The attack vector tests effectively cover front-running protection (duplicate payment references) and access control attacks (unauthorized role access). These tests verify that the contract properly enforces role-based permissions and prevents common attack patterns.


1041-1108: LGTM! Thorough boundary value tests.

The boundary value tests cover minimum amounts (1 wei), time boundaries using block timestamps, and maximum fee basis points (100%). Note that lines 1062-1063 demonstrate the proper way to obtain blockchain timestamps, which could be applied to the time constants initialization as suggested earlier.


232-270: Validation delegation pattern is correctly implemented and documented.

The wrapper properly delegates validation to the underlying escrow contract. The wrapper validates only critical addresses (payer, merchant, operator, token) but intentionally skips validation of amounts, expiry times, and time ordering—delegating these checks to the escrow contract's authorize function. The test suite accurately documents this behavior. This is a valid thin-wrapper design pattern.


614-651: Verify integration test coverage for refund execution.

The claim that refund functionality "is tested in integration tests with real contracts" (lines 648-650) is unsubstantiated. Inspection found:

  • Smart-contracts: access control only (1 test)
  • Payment-processor: function encoding validation only
  • Integration tests: refund addresses configured as parameters, but no actual refund execution tests

Confirm that integration tests actually execute refundPayment() and verify:

  • Tokens transferred to payer
  • Payment state updated correctly
  • Only operator can initiate refund

If integration tests don't cover this, add executable refund tests to validate the full flow.

Copy link

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

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

Looking good, nice work on this and the exhaustive test coverage 🔥
The TS wrapper looks nice and clean, and the contract itself has a lot of comments that explain what's going on.
🚢

Copy link
Member

@MantisClone MantisClone left a comment

Choose a reason for hiding this comment

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

Partial review - ERC20CommerceEscrowWrapper.sol only

I've reviewed ERC20CommerceEscrowWrapper.sol and posted comments on:

  • Missing feeBps upper bound validation (high priority)
  • PaymentData struct packing opportunity (45% storage savings)
  • InvalidPayer error for better debugging
  • State delegation to Commerce Escrow (architectural note)

Haven't reviewed the other 16 files yet. The contract looks solid overall - main concerns are the fee validation and storage optimization.

bytes8 paymentReference,
uint256 captureAmount,
uint16 feeBps,
address feeReceiver
Copy link
Member

Choose a reason for hiding this comment

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

Fee basis points validation missing - could cause underflow

The feeBps parameter has no upper bound validation. If feeBps > 10000 (100%), the fee calculation would result in feeAmount > captureAmount, causing merchantAmount underflow and transaction revert.

Recommendation: Add validation before fee calculation:

if (feeBps > 10000) revert InvalidFeeBps();

This issue also affects _transferToMerchant (line 524).

mapping(bytes8 => PaymentData) public payments;

/// @notice Internal payment data structure
struct PaymentData {
Copy link
Member

Choose a reason for hiding this comment

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

PaymentData struct should use struct packing for gas efficiency

The current PaymentData struct uses 11 storage slots when it could use only 6 with proper packing. This wastes ~40% gas on every payment operation.

The Commerce Escrow already uses packed structs (uint120 for amounts, uint48 for timestamps). The wrapper should follow the same pattern:

Recommended packed layout:

struct PaymentData {
  address payer;              // Slot 0 (20 bytes)
  bool isActive;              // Slot 0 (1 byte) ← PACKED
  
  address merchant;           // Slot 1 (20 bytes)
  uint96 amount;              // Slot 1 (12 bytes) ← PACKED
  
  address operator;           // Slot 2 (20 bytes)
  uint96 maxAmount;           // Slot 2 (12 bytes) ← PACKED
  
  address token;              // Slot 3 (20 bytes)
  uint48 preApprovalExpiry;   // Slot 3 (6 bytes) ← PACKED
  uint48 authorizationExpiry; // Slot 3 (6 bytes) ← PACKED
  
  uint48 refundExpiry;        // Slot 4 (6 bytes)
  bytes32 commercePaymentHash;// Slot 5 (32 bytes)
}

Benefits:

  • 45% storage gas savings per payment (11 slots → 6 slots)
  • Type consistency with Commerce Escrow interface
  • Eliminates overflow validation in _createPaymentInfoFromStored (types match escrow requirements)
  • uint96 supports up to ~79B tokens (18 decimals) - sufficient for all practical use cases
  • uint48 timestamps valid until year 8,921,556 - no practical limitation

mapping(bytes8 => PaymentData) public payments;

/// @notice Internal payment data structure
struct PaymentData {
Copy link
Member

Choose a reason for hiding this comment

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

Consider delegating existence check to Commerce Escrow

The isActive boolean duplicates information already tracked by Commerce Escrow's paymentState[hash].hasCollectedPayment.

Could simplify by checking commerceEscrow.paymentState(hash).hasCollectedPayment instead of maintaining separate wrapper state. This would eliminate potential state synchronization issues and reduce storage costs.

Copy link
Member

@MantisClone MantisClone left a comment

Choose a reason for hiding this comment

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

Partial review - Test file and deployment script

I've reviewed the test file and deployment configuration, posting comments on:

Test file (ERC20CommerceEscrowWrapper.test.ts):

  • Missing token balance verification across all test cases (critical priority)
  • Fee calculation tests need balance checks, not just event verification
  • Zero refund test coverage (medium priority - document if deferred)

Deployment script (constructor-args.ts):

  • Hardcoded Commerce Escrow address needs network-specific artifacts pattern

Haven't reviewed the other 14 files yet. Test coverage is comprehensive for state/events but needs token movement verification.

Copy link
Member

Choose a reason for hiding this comment

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

Tests verify event emissions and state storage but never check actual token balance changes. This is a critical gap - events can emit correctly while tokens fail to transfer.

Missing across all functions:

  • ✅ Authorization: Verify payer → escrow token flow
  • ✅ Capture: Verify escrow → merchant + fee receiver split
  • ✅ Void: Verify escrow → payer refund
  • ✅ Charge: Verify payer → merchant + fee receiver
  • ✅ Reclaim: Verify escrow → payer
  • ✅ Refund: Verify operator → payer

Example fix for capture:

it('should transfer correct token amounts during capture', async () => {
  const merchantBefore = await testERC20.balanceOf(merchantAddress);
  const feeReceiverBefore = await testERC20.balanceOf(feeReceiverAddress);
  
  await wrapper.connect(operator).capturePayment(
    paymentReference, captureAmount, feeBps, feeReceiverAddress
  );
  
  const feeAmount = captureAmount.mul(feeBps).div(10000);
  expect(await testERC20.balanceOf(merchantAddress))
    .to.equal(merchantBefore.add(captureAmount.sub(feeAmount)));
  expect(await testERC20.balanceOf(feeReceiverAddress))
    .to.equal(feeReceiverBefore.add(feeAmount));
  expect(await testERC20.balanceOf(wrapper.address))
    .to.equal(0, 'Tokens should not get stuck in wrapper');
});

Checklist:

  • Add balance checks to authorization tests
  • Add balance checks to capture tests
  • Add balance checks to void tests
  • Add balance checks to charge tests
  • Add balance checks to reclaim tests
  • Add balance checks to refund tests (see separate comment)

.capturePayment(authParams.paymentReference, amount, feeBps, feeReceiverAddress);
});

it('should revert if called by non-operator (access control test)', async () => {
Copy link
Member

Choose a reason for hiding this comment

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

Refund functionality has zero happy path tests (only access control). If refund flows are deferred to future work, consider:

  1. Add TODO comment indicating refund tests are planned
  2. Document refund flow requirements so future tests cover:
    • Operator liquidity provision
    • Token transfer verification
    • Partial refund scenarios
  3. Add integration tests if unit tests are too complex with mocks

Current note (lines 640-652):

// Note: Refund functionality test is complex due to mock contract interactions
// The wrapper expects operator to have tokens and approve the tokenCollector
// This is tested in integration tests with real contracts

Suggested update:

// TODO: Add refund functionality tests in future PR
// Refund flows are deferred to post-MVP work
// Integration tests should cover:
// - Operator provides liquidity for refund
// - Payer receives refund tokens
// - Partial refunds work correctly

Not blocking if refund is out of scope for initial release.

});

it('should charge payment successfully', async () => {
const expectedFeeAmount = amount.mul(feeBps).div(10000);
Copy link
Member

Choose a reason for hiding this comment

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

Fee calculation tests verify events but not actual token amounts

The test calculates expectedFeeAmount but only verifies event emissions - it never checks that the fee receiver's token balance actually increased by this amount.

Current gap:

const expectedFeeAmount = amount.mul(feeBps).div(10000);
// ... test only checks events, not balanceOf()

Recommended improvement to existing fee tests:
Add balance verification to existing chargePayment tests (and similar capture tests):

// Before charging payment
const merchantBalanceBefore = await testERC20.balanceOf(merchantAddress);
const feeReceiverBalanceBefore = await testERC20.balanceOf(feeReceiverAddress);

const tx = await wrapper.chargePayment(chargeParams);

// After charging payment - verify actual token transfers
const merchantBalanceAfter = await testERC20.balanceOf(merchantAddress);
const feeReceiverBalanceAfter = await testERC20.balanceOf(feeReceiverAddress);

const expectedFeeAmount = amount.mul(feeBps).div(10000);
const expectedMerchantAmount = amount.sub(expectedFeeAmount);

expect(merchantBalanceAfter.sub(merchantBalanceBefore)).to.equal(expectedMerchantAmount);
expect(feeReceiverBalanceAfter.sub(feeReceiverBalanceBefore)).to.equal(expectedFeeAmount);

Also test edge cases:

  • 0% fee (feeBps = 0): verify merchant gets full amount, fee receiver gets nothing
  • 100% fee (feeBps = 10000): verify merchant gets nothing, fee receiver gets all
  • 2.5% fee (current): verify exact split matches calculation

This ensures fees are actually transferred, not just emitted in events.

Severity: High - Missing critical validation of actual token transfers

Copy link
Member

Choose a reason for hiding this comment

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

Fee mechanism design needs clarification

The current fee implementation has some architectural constraints that should be documented:

Current implementation:

  • Fee is always paid by the merchant (subtracted from capture amount at line 389)
  • Fee supports single recipient only (one feeReceiver address)
  • Fee is a platform fee (not Request Network protocol/API fee)
  • Fee calculation: feeAmount = (captureAmount * feeBps) / 10000

Design questions to clarify:

  1. Who pays the fee?

    • Current: Merchant receives captureAmount - feeAmount
    • Alternative: Could payer pay fee on top (like amount + feeAmount)?
    • Recommendation: Document this is platform fee, merchant pays
  2. Single vs multiple fee recipients:

    • Current: One feeReceiver address
    • Future need: Request Network API fee + Platform fee split?
    • Recommendation: Document future enhancement path if dual fees are needed
  3. Fee type naming:

    • "Fee" is ambiguous (platform? protocol? API?)
    • Recommendation: Clarify in comments this is "Platform Fee" to distinguish from RN protocol fees
  4. Configurability:

    • Should there be an option for payer-pays-fee vs merchant-pays-fee?
    • Currently hard-coded as merchant-pays

Suggested documentation additions:

/// @param feeBps Platform fee in basis points (paid by merchant, subtracted from capture)
/// @param feeReceiver Platform fee recipient (separate from RN protocol fees)

Severity: Medium - Architectural clarity needed for future extensibility

@MantisClone MantisClone mentioned this pull request Nov 7, 2025
Copy link
Member

@MantisClone MantisClone left a comment

Choose a reason for hiding this comment

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

Code Review Summary

Completed comprehensive review of all 18 files in this PR. The Commerce Escrow payment functionality is well-implemented with proper integration into the Request Network ecosystem.

Highlights:
✅ Smart contract follows established patterns and includes proper validation
✅ Type definitions are comprehensive and match contract structures
✅ Deployment scripts properly configured for CREATE2 deployment
✅ Test coverage is excellent for encoding and integration flows
✅ Payment processor integration follows codebase conventions

Key Issue Identified:

  • Interface usage inconsistency in erc20-commerce-escrow-wrapper.ts (see inline comment)

The implementation is production-ready after addressing the inline comment regarding Interface usage documentation.

const wrapperContract = erc20CommerceEscrowWrapperArtifact.connect(network, provider);

// Use utils.Interface to encode with the raw ABI to avoid TypeScript interface issues
const iface = new utils.Interface(
Copy link
Member

Choose a reason for hiding this comment

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

Inconsistent Interface usage pattern

encodeAuthorizePayment and encodeChargePayment use utils.Interface workaround (lines 127, 218) while encodeCapturePayment uses direct interface.encodeFunctionData (line 169).

Reason: Functions with many parameters (12+ params) hit TypeScript limitations when encoding. The workaround is needed for authorize/charge but not for simpler functions like capture (4 params).

Recommendation: Add JSDoc comment to document the pattern:

/**
 * @remarks
 * Uses utils.Interface to handle large parameter count (TypeScript encoding limitation).
 * Similar pattern in single-request-forwarder.ts.
 */

This makes the inconsistency intentional rather than appearing accidental.

…testing scripts

- Introduced a new deployment script for ERC20CommerceEscrowWrapper, utilizing official Base contracts.
- Added a test script for Base Sepolia deployment, demonstrating wallet creation and deployment process.
- Implemented a malicious token contract for testing reentrancy protection in ERC20CommerceEscrowWrapper.
- Enhanced unit tests to validate reentrancy protection across various payment functions, ensuring robustness against attacks.
…oving USDT handling

- Removed the special handling for USDT in `encodeSetCommerceEscrowAllowance` and `encodeSetRecurringAllowance` functions, streamlining the approval process to a single transaction for all ERC20 tokens.
- Updated related tests to reflect the changes, ensuring they now validate the single transaction behavior for token approvals.
…ency

- Reorganized the PaymentData struct to reduce storage slots from 11 to 6, achieving approximately 45% gas savings.
- Updated data types for amount and expiry fields to smaller types (uint96, uint48) to enhance storage efficiency.
- Adjusted related functions to ensure proper validation and casting of payment parameters, maintaining functionality while improving performance.
…lag and error handling

- Added an `isActive` boolean to the `PaymentData` struct for efficient existence checks and improved state management.
- Introduced a new `InvalidPayer` error for clearer error handling when the caller is not the designated payer.
- Updated related logic to utilize the new error for better clarity in payment validation.
…ted artifacts for fee handling

- Enhanced the ERC20CommerceEscrowWrapper contract to implement a fee architecture, allowing for Request Network platform fees to be deducted from payments.
- Updated the capture and transfer functions to bypass Commerce Escrow fees, ensuring all fee handling is managed through ERC20FeeProxy for compatibility and tracking.
- Introduced the AuthCaptureEscrow artifact and updated constructor arguments to utilize the deployed address dynamically.
- Added detailed comments and remarks in the code to clarify the fee structure and its implications for payment processing.
Copy link
Contributor

@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: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cc4dac and 3a49f20.

📒 Files selected for processing (10)
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1 hunks)
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts (1 hunks)
  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts (1 hunks)
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (1 hunks)
  • packages/smart-contracts/hardhat.config.ts (4 hunks)
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts (1 hunks)
  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts (1 hunks)
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1 hunks)
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol (1 hunks)
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (50)
📓 Common learnings
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.
📚 Learning: 2024-10-28T20:02:48.835Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:29-29
Timestamp: 2024-10-28T20:02:48.835Z
Learning: In test deployment scripts (e.g., files like 'test-deploy-*.ts' in 'packages/smart-contracts/scripts'), it's acceptable to use `console.log` for logging.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-10-28T20:00:25.780Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:14-32
Timestamp: 2024-10-28T20:00:25.780Z
Learning: In test files, such as `packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts`, extensive error handling and input validation are considered unnecessary.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-11T16:10:26.692Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1486
File: packages/smart-contracts/deploy/deploy-zk-single-request-proxy.ts:1-24
Timestamp: 2024-11-11T16:10:26.692Z
Learning: The team prefers to maintain individual deployment scripts for each network in `packages/smart-contracts/deploy`, rather than consolidating them into a unified script.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-05T05:33:32.481Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:38-43
Timestamp: 2024-11-05T05:33:32.481Z
Learning: In the RequestNetwork codebase, setup scripts such as `setupSingleRequestProxyFactory.ts` do not include contract existence checks before interacting with contracts, even though scripts like `check-deployer.ts` do include such checks.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-12-13T10:00:17.504Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1512
File: packages/integration-test/test/lit-protocol.test.ts:48-50
Timestamp: 2024-12-13T10:00:17.504Z
Learning: In `packages/integration-test/test/lit-protocol.test.ts`, the wallet private key `'0x7b595b2bb732edddc4d4fe758ae528c7a748c40f0f6220f4494e214f15c5bfeb'` is fixed and can be hardcoded in the test file.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-05T05:33:36.551Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:30-36
Timestamp: 2024-11-05T05:33:36.551Z
Learning: In the RequestNetwork project, admin scripts like `setupSingleRequestProxyFactory.ts` in `packages/smart-contracts/scripts-create2/contract-setup/` do not require extensive error checking.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2025-06-23T09:32:16.214Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1633
File: packages/smart-contracts/scripts/test-deploy-erc20-recurring-payment-proxy.ts:16-16
Timestamp: 2025-06-23T09:32:16.214Z
Learning: Test deployment scripts in the RequestNetwork repository (files with `test-deploy-` prefix) use the same deployer address for multiple roles for simplicity in local testing environments. Production deployments use separate addresses configured through environment variables.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T20:00:33.707Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:4-7
Timestamp: 2024-10-28T20:00:33.707Z
Learning: In TypeScript test files (e.g., `test-deploy-single-request-proxy.ts`), it's acceptable to use `string` types for Ethereum addresses in interfaces (like `FeeProxyAddresses`), as stricter type safety is not necessary.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-05T05:33:36.189Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:26-28
Timestamp: 2024-11-05T05:33:36.189Z
Learning: In the `requestNetwork` project's TypeScript setup scripts located in `packages/smart-contracts/scripts-create2/contract-setup`, `Promise.all` is used for asynchronous network setup tasks to maintain consistency across scripts.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-12-04T05:01:13.722Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/hinkalRequestData.ts:0-0
Timestamp: 2024-12-04T05:01:13.722Z
Learning: In `packages/usage-examples/src/hinkal/hinkalRequestData.ts`, when integrating Hinkal, it's acceptable for the network to be set to 'base' as the payment chain while using the Sepolia gateway URL ('https://sepolia.gateway.request.network') as the request storage chain.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-12-18T03:53:54.370Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:38-38
Timestamp: 2024-12-18T03:53:54.370Z
Learning: In `packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts`, mainnet RPC is intentionally used for real on-chain tests as confirmed by MantisClone.

Applied to files:

  • packages/smart-contracts/scripts/test-base-sepolia-deployment.ts
  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-11-08T18:24:06.144Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:237-246
Timestamp: 2024-11-08T18:24:06.144Z
Learning: In `packages/payment-processor/test/payment/single-request-proxy.test.ts`, when asserting the `feeProxyUsed` in emitted events from `SingleRequestProxyFactory`, retrieve the `erc20FeeProxy` (or `ethereumFeeProxy`) public variable from the `SingleRequestProxyFactory` contract instead of using `wallet.address`.

Applied to files:

  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-12T16:54:02.702Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:104-104
Timestamp: 2024-11-12T16:54:02.702Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, when the smart contract has not changed, event argument names such as `proxyAddress` remain the same, even if variable names in the code are updated to use new terminology like `forwarderAddress`.

Applied to files:

  • packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-12T17:48:47.072Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:211-219
Timestamp: 2024-11-12T17:48:47.072Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, the error handling logic in `payWithEthereumSingleRequestForwarder` is correct and does not require changes to differentiate between ERC20 and Ethereum SingleRequestForwarder contracts.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-04T14:32:57.040Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc20-fee-proxy.ts:186-186
Timestamp: 2024-11-04T14:32:57.040Z
Learning: In the `preparePrivateErc20FeeProxyPaymentTransaction` function in `packages/payment-processor/src/payment/erc20-fee-proxy.ts`, we should not make an allowance call on the token contract, as it is not relevant to our use case.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-06T14:48:18.698Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1484
File: packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts:0-0
Timestamp: 2024-11-06T14:48:18.698Z
Learning: In `packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts`, when the existing happy path tests are deemed sufficient, additional test cases may not be necessary.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-29T09:00:54.169Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:202-209
Timestamp: 2024-10-29T09:00:54.169Z
Learning: In the `packages/payment-processor/src/payment/single-request-proxy.ts` file, within the `payWithEthereumSingleRequestProxy` function, the current error handling is acceptable as per the project's expectations.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-29T08:02:02.600Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:138-139
Timestamp: 2024-10-29T08:02:02.600Z
Learning: When testing invalid requests in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to use `ts-expect-error` to suppress TypeScript errors when the request intentionally lacks required properties.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-21T09:06:12.938Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:87-119
Timestamp: 2024-11-21T09:06:12.938Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, mocks like `fakeEpkCipherProvider` do not require extensive test coverage for input validation and error handling.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-17T16:00:11.730Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:30-34
Timestamp: 2024-10-17T16:00:11.730Z
Learning: In `packages/smart-contracts/src/contracts/test/UsdtFake.sol`, the code is part of the test harness and not intended for production, so deviations from ERC20 standards are acceptable.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-10-28T15:52:05.032Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:156-160
Timestamp: 2024-10-28T15:52:05.032Z
Learning: In the `payRequestWithSingleRequestProxy` function of `single-request-proxy.ts`, failing to retrieve `tokenAddress()` is expected for `EthereumSingleRequestProxy` contracts and is not an error.

Applied to files:

  • packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts
  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, when decoding event data, the team prefers not to include documentation of the event data structure if maintaining it would be difficult.

Applied to files:

  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, the team prefers not to store or validate decoded values that are not needed.

Applied to files:

  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T14:31:29.664Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:15-16
Timestamp: 2024-11-04T14:31:29.664Z
Learning: In `packages/payment-processor/src/payment/prepared-transaction.ts`, for the `IPreparedPrivateTransaction` interface, use `string[]` for the `ops` field since Hinkal's relevant functions accept arrays of `string` as inputs.

Applied to files:

  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-05T14:43:16.298Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol:46-46
Timestamp: 2024-10-05T14:43:16.298Z
Learning: In `packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol`, within the `receive()` function, it's acceptable to approve the entire `balance` to `erc20FeeProxy` because `balance == paymentAmount + feeAmount`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-12-09T18:59:04.613Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts:80-99
Timestamp: 2024-12-09T18:59:04.613Z
Learning: In the `RequestNetwork` codebase, payment processor functions such as `payErc20ProxyRequestFromHinkalShieldedAddress` in `packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts` should not include explicit request validation or try/catch blocks, and should rely on the underlying components (like `hinkalObject`) to handle error reporting.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-04T20:54:04.489Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:9-17
Timestamp: 2024-11-04T20:54:04.489Z
Learning: In the `IPreparedPrivateTransaction` interface within `packages/payment-processor/src/payment/prepared-transaction.ts`, the team prefers concise documentation comments and avoids overly verbose explanations.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T21:11:48.524Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:123-184
Timestamp: 2024-10-28T21:11:48.524Z
Learning: When suggesting error handling improvements in `packages/payment-processor/src/payment/single-request-proxy.ts`, avoid recommending try-catch blocks that re-throw errors without additional processing.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-29T08:03:10.463Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:225-228
Timestamp: 2024-10-29T08:03:10.463Z
Learning: In 'packages/payment-processor/test/payment/single-request-proxy.test.ts' (TypeScript), when testing with an invalid proxy address, we should not use the zero address.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-09-27T11:42:01.062Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:0-0
Timestamp: 2024-09-27T11:42:01.062Z
Learning: In the `createEthereumSingleRequestProxy` function, it's acceptable for `_feeAddress` to be the zero address, as setting the fee address to zero is a common practice. Adding zero address checks is unnecessary and adds extra gas cost.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-17T16:00:03.170Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:63-66
Timestamp: 2024-10-17T16:00:03.170Z
Learning: In test harness contracts like `UsdtFake.sol`, which are not meant for production, having an unrestricted `mint` function is acceptable.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:53:41.522Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:5-13
Timestamp: 2024-11-04T20:53:41.522Z
Learning: When reviewing the RequestNetwork codebase, avoid suggesting the addition of example usage in documentation if it would make the comments overly verbose, especially for functions like `prepareHinkal` in `packages/payment-processor/src/payment/prepare-hinkal.ts`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:54:11.202Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:20-20
Timestamp: 2024-11-04T20:54:11.202Z
Learning: In `packages/payment-processor/src/payment/prepare-hinkal.ts`, when passing `undefined` parameters to functions like `initProviderAdapter`, it's acceptable not to add comments explaining the `undefined` parameter to avoid overly verbose code.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-22T13:13:26.166Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:0-0
Timestamp: 2024-11-22T13:13:26.166Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, the `FakeLitProtocolProvider` class uses `{}` as the return type for its methods `encrypt` and `decrypt`. Changing the return type to a more specific interface caused issues, so the current return type `{}` should remain as is.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-05T14:43:14.816Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:11-15
Timestamp: 2024-10-05T14:43:14.816Z
Learning: In the `EthereumSingleRequestProxy` contract, the state variables `payee`, `paymentReference`, `feeAddress`, `feeAmount`, and `ethereumFeeProxy` should remain public, as they need to be accessed externally.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-08T18:24:19.095Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:198-206
Timestamp: 2024-11-08T18:24:19.095Z
Learning: In tests for `SingleRequestProxyFactory`, the `feeProxyUsed` in events should be verified by retrieving the `ethereumFeeProxy` public variable from the `SingleRequestProxyFactory` contract, not `wallet.address`.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-15T07:50:54.734Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:77-78
Timestamp: 2024-10-15T07:50:54.734Z
Learning: In the `receive()` function of the `EthereumSingleRequestProxy` contract (`packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol`), the current error handling for the call to `ethereumFeeProxy` is considered sufficient, and no additional error handling is required.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2025-06-23T09:35:04.263Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1633
File: packages/smart-contracts/src/contracts/ERC20RecurringPaymentProxy.sol:92-133
Timestamp: 2025-06-23T09:35:04.263Z
Learning: In the ERC20RecurringPaymentProxy contract, events were intentionally omitted to save gas costs since the underlying ERC20FeeProxy contract already emits events when payments are processed. This avoids duplicate event emissions while maintaining observability.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-28T20:00:53.026Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/src/lib/artifacts/SingleRequestProxyFactory/0.1.0.json:24-124
Timestamp: 2024-10-28T20:00:53.026Z
Learning: In our smart contracts, we should remove the `indexed` keyword from all event parameters except for `paymentReference`, as we use the payment-subgraph for indexing and this reduces gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-15T07:50:58.094Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:22-27
Timestamp: 2024-10-15T07:50:58.094Z
Learning: In the `SingleRequestProxyFactory` contract, the `paymentReference` parameter in events should remain `indexed`, even if removing `indexed` could reduce gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-17T18:33:41.124Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/EthereumSingleRequestProxy.test.ts:0-0
Timestamp: 2024-10-17T18:33:41.124Z
Learning: In the `EthereumSingleRequestProxy` contract, the custom reentrancy guard is nearly identical to OpenZeppelin's ReentrancyGuard, except that it allows the first reentrancy call from the `ERC20FeeProxy`. We assume it works correctly without needing further tests.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-10-05T14:43:07.965Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:19-23
Timestamp: 2024-10-05T14:43:07.965Z
Learning: In the `EthereumSingleRequestProxy` contract, a custom reentrancy guard is used instead of OpenZeppelin's `ReentrancyGuard`, with minor edits to allow reentrancy by the `ethereumFeeProxy`.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-12-04T05:05:19.610Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:0-0
Timestamp: 2024-12-04T05:05:19.610Z
Learning: The function `createRequestForHinkal` in `erc-20-private-payment-hinkal.test.ts` is intended for testing purposes only and should remain in the test directory.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-10-02T05:15:18.868Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1316
File: packages/utils/test/retry.test.ts:149-216
Timestamp: 2024-10-02T05:15:18.868Z
Learning: Developers prefer unrolled loops and explicit comments in test code, particularly in 'retry.test.ts' for the exponential backoff test, to show the number of calls and total elapsed time for retries, rather than refactoring using loops.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-04T12:18:13.888Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/testPayErc20FeeProxyRequestHinkal.ts:19-27
Timestamp: 2024-11-04T12:18:13.888Z
Learning: In the file `packages/usage-examples/src/hinkal/testPayErc20FeeProxyRequestHinkal.ts`, when using `payPrivateErc20FeeProxyRequest`, the returned `tx` is a `RelayerTransaction`, so calling `.wait()` on it is unnecessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-05T16:58:18.471Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/payment-detection/test/provider.test.ts:25-25
Timestamp: 2024-11-05T16:58:18.471Z
Learning: In `provider.test.ts`, when testing `getDefaultProvider`, we use a chain that Infura supports but is not in our own RPC list (such as `maticmum`) to ensure that the function correctly falls back to `InfuraProvider`.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
🧬 Code graph analysis (4)
packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts (1)
packages/smart-contracts/scripts/deploy-one.ts (1)
  • deployOne (45-152)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (4)
packages/types/src/payment-types.ts (6)
  • CommerceEscrowPaymentData (419-431)
  • CommerceEscrowAuthorizeParams (436-449)
  • CommerceEscrowCaptureParams (454-459)
  • CommerceEscrowChargeParams (464-467)
  • CommerceEscrowRefundParams (472-477)
  • CommerceEscrowPaymentState (482-486)
packages/types/src/currency-types.ts (1)
  • EvmChainName (6-35)
packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/index.ts (1)
  • erc20CommerceEscrowWrapperArtifact (7-42)
packages/payment-processor/src/payment/erc20.ts (1)
  • getErc20Allowance (96-104)
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (2)
packages/types/src/currency-types.ts (1)
  • EvmChainName (6-35)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (23)
  • AuthorizePaymentParams (9-9)
  • CapturePaymentParams (10-10)
  • ChargePaymentParams (11-11)
  • RefundPaymentParams (12-12)
  • getCommerceEscrowWrapperAddress (22-30)
  • encodeSetCommerceEscrowAllowance (70-90)
  • getPayerCommerceEscrowAllowance (42-58)
  • encodeAuthorizePayment (101-132)
  • encodeCapturePayment (143-159)
  • encodeVoidPayment (170-181)
  • encodeChargePayment (192-225)
  • encodeReclaimPayment (236-247)
  • encodeRefundPayment (258-274)
  • authorizePayment (285-309)
  • capturePayment (320-344)
  • voidPayment (355-379)
  • chargePayment (390-414)
  • reclaimPayment (425-449)
  • refundPayment (460-484)
  • getPaymentData (495-521)
  • getPaymentState (532-545)
  • canCapture (556-567)
  • canVoid (578-589)
packages/smart-contracts/hardhat.config.ts (1)
packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts (1)
  • deployERC20CommerceEscrowWrapper (23-91)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (3)
packages/payment-processor/test/payment/erc-20-recurring-payment.test.ts (2)

112-126: LGTM! Test simplification is appropriate.

The consolidated test effectively validates the core approval encoding behavior. The removal of USDT-specific branches suggests that non-standard token handling is addressed elsewhere or no longer required for this flow.

Based on learnings


128-141: LGTM! Good error path coverage.

The test properly validates that the function throws with a clear diagnostic message when the proxy cannot be located on the specified network.

packages/payment-processor/src/payment/erc20-recurring-payment-proxy.ts (1)

85-85: ****

The review comment conflates changes from different functions. The encodeSetRecurringAllowance function in erc20-recurring-payment-proxy.ts has never contained an isUSDT parameter, and the current implementation has always returned a single-element transaction array. Git history confirms no such parameter existed in this file.

The concerns about USDT two-transaction logic appear to relate to a different function (encodeSetCommerceEscrowAllowance) or a different PR entirely. The change at line 85 is the standard approve transaction encoding, with no USDT-specific handling in this recurring payment function.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@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: 3

♻️ Duplicate comments (2)
packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (2)

335-363: Add validation for amount parameter to prevent silent truncation.

amount is cast to uint96 (line 354) without validation. If amount > type(uint96).max, it silently truncates, corrupting payment data.

Unlike maxAmount (validated in _createPaymentInfo line 310), amount is never validated before storage. The comment at line 336 is misleading.

Add validation before casting:

 function _storePaymentData(
   bytes8 paymentReference,
   address payer,
   address merchant,
   address operator,
   address token,
   uint256 amount,
   uint256 maxAmount,
   uint256 preApprovalExpiry,
   uint256 authorizationExpiry,
   uint256 refundExpiry,
   bytes32 commerceHash
 ) internal {
+  if (amount > type(uint96).max) revert ScalarOverflow();
+
   payments[paymentReference] = PaymentData({

408-456: Add feeBps validation to prevent underflow.

If feeBps > 10000 (>100%), the fee calculation produces feeAmount > captureAmount, causing merchantAmount underflow and transaction revert (line 432).

Add validation and define the error:

+error InvalidFeeBps();
+
 function capturePayment(
   bytes8 paymentReference,
   uint256 captureAmount,
   uint16 feeBps,
   address feeReceiver
 ) external nonReentrant onlyOperator(paymentReference) {
+  if (feeBps > 10000) revert InvalidFeeBps();
+
   PaymentData storage payment = payments[paymentReference];

This issue also affects _transferToMerchant (used by chargePayment).

🧹 Nitpick comments (2)
packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts (1)

16-17: Clarify deployment comment.

The comment "Base Sepolia deployment (same address as mainnet via CREATE2)" is confusing. Sepolia is a testnet for Ethereum mainnet, whereas "Base Sepolia" would typically refer to Base's testnet. Based on line 17 showing sepolia: as the network key, this appears to be the deployment on Base Sepolia testnet (not Ethereum Sepolia).

Consider clarifying the comment:

-        // Base Sepolia deployment (same address as mainnet via CREATE2)
+        // Base Sepolia (testnet) deployment (same address across networks via CREATE2)
         sepolia: {
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1)

70-90: Consider improving USDT compatibility handling in encodeSetCommerceEscrowAllowance.

The function encodes an approve call for payer→wrapper allowance. On Ethereum mainnet, USDT requires resetting approval to 0 before setting a new non-zero value—if a payer has an existing allowance, this transaction will revert. The function's return type already supports multiple transactions Array<{ to: string; data: string; value: number }>, making it suitable for the pattern.

Recommended fix: Either encode [approve(0), approve(amount)] when needed, or document this limitation and the USDT workaround in the JSDoc. This improves robustness for callers of this public API, particularly on networks where USDT is used.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a49f20 and cd4fbec.

📒 Files selected for processing (6)
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1 hunks)
  • packages/smart-contracts/scripts-create2/constructor-args.ts (1 hunks)
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/0.1.0.json (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts (1 hunks)
  • packages/smart-contracts/src/lib/artifacts/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/smart-contracts/src/lib/artifacts/index.ts
🧰 Additional context used
🧠 Learnings (37)
📓 Common learnings
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.
📚 Learning: 2024-11-12T16:52:41.557Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/smart-contracts/src/lib/artifacts/SingleRequestProxyFactory/index.ts:5-5
Timestamp: 2024-11-12T16:52:41.557Z
Learning: When the smart contracts are not being modified, types like `SingleRequestProxyFactory` in `packages/smart-contracts/src/lib/artifacts/SingleRequestProxyFactory/index.ts` should remain unchanged, even if terminology elsewhere in the code is updated.

Applied to files:

  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts
  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/0.1.0.json
📚 Learning: 2024-09-27T11:54:45.798Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/scripts-create2/utils.ts:23-23
Timestamp: 2024-09-27T11:54:45.798Z
Learning: When a contract has not been deployed yet and thus has no artifact, the `getArtifact` function will be updated after deployment.

Applied to files:

  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts
📚 Learning: 2024-10-30T17:54:36.071Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/update-fee-proxies.ts:80-85
Timestamp: 2024-10-30T17:54:36.071Z
Learning: When dealing with contract ABIs, use `artifact.getContractAbi()` instead of manually redefining the ABI.

Applied to files:

  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts
  • packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/0.1.0.json
📚 Learning: 2024-11-12T16:54:02.702Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:104-104
Timestamp: 2024-11-12T16:54:02.702Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, when the smart contract has not changed, event argument names such as `proxyAddress` remain the same, even if variable names in the code are updated to use new terminology like `forwarderAddress`.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-12T17:48:47.072Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:211-219
Timestamp: 2024-11-12T17:48:47.072Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, the error handling logic in `payWithEthereumSingleRequestForwarder` is correct and does not require changes to differentiate between ERC20 and Ethereum SingleRequestForwarder contracts.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-08T18:24:06.144Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:237-246
Timestamp: 2024-11-08T18:24:06.144Z
Learning: In `packages/payment-processor/test/payment/single-request-proxy.test.ts`, when asserting the `feeProxyUsed` in emitted events from `SingleRequestProxyFactory`, retrieve the `erc20FeeProxy` (or `ethereumFeeProxy`) public variable from the `SingleRequestProxyFactory` contract instead of using `wallet.address`.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-09-27T11:42:01.062Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:0-0
Timestamp: 2024-09-27T11:42:01.062Z
Learning: In the `createEthereumSingleRequestProxy` function, it's acceptable for `_feeAddress` to be the zero address, as setting the fee address to zero is a common practice. Adding zero address checks is unnecessary and adds extra gas cost.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-29T08:03:10.463Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:225-228
Timestamp: 2024-10-29T08:03:10.463Z
Learning: In 'packages/payment-processor/test/payment/single-request-proxy.test.ts' (TypeScript), when testing with an invalid proxy address, we should not use the zero address.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T14:32:57.040Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc20-fee-proxy.ts:186-186
Timestamp: 2024-11-04T14:32:57.040Z
Learning: In the `preparePrivateErc20FeeProxyPaymentTransaction` function in `packages/payment-processor/src/payment/erc20-fee-proxy.ts`, we should not make an allowance call on the token contract, as it is not relevant to our use case.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-05T05:33:32.481Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:38-43
Timestamp: 2024-11-05T05:33:32.481Z
Learning: In the RequestNetwork codebase, setup scripts such as `setupSingleRequestProxyFactory.ts` do not include contract existence checks before interacting with contracts, even though scripts like `check-deployer.ts` do include such checks.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T15:52:05.032Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:156-160
Timestamp: 2024-10-28T15:52:05.032Z
Learning: In the `payRequestWithSingleRequestProxy` function of `single-request-proxy.ts`, failing to retrieve `tokenAddress()` is expected for `EthereumSingleRequestProxy` contracts and is not an error.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T18:24:19.095Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:198-206
Timestamp: 2024-11-08T18:24:19.095Z
Learning: In tests for `SingleRequestProxyFactory`, the `feeProxyUsed` in events should be verified by retrieving the `ethereumFeeProxy` public variable from the `SingleRequestProxyFactory` contract, not `wallet.address`.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-04T14:30:34.835Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/hinkalRequestData.ts:5-6
Timestamp: 2024-11-04T14:30:34.835Z
Learning: In `packages/usage-examples/src/hinkal/hinkalRequestData.ts`, it's acceptable to hardcode the USDC contract address without creating a mapping of USDC assets on specific networks.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
📚 Learning: 2024-11-05T05:04:01.710Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:45-58
Timestamp: 2024-11-05T05:04:01.710Z
Learning: When executing blockchain transactions in scripts (e.g., in `packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts`), ensure that transactions are executed serially rather than in parallel to maintain correct execution order and prevent potential issues.

Applied to files:

  • packages/smart-contracts/scripts-create2/constructor-args.ts
📚 Learning: 2024-12-09T18:59:04.613Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts:80-99
Timestamp: 2024-12-09T18:59:04.613Z
Learning: In the `RequestNetwork` codebase, payment processor functions such as `payErc20ProxyRequestFromHinkalShieldedAddress` in `packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts` should not include explicit request validation or try/catch blocks, and should rely on the underlying components (like `hinkalObject`) to handle error reporting.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-04T14:31:29.664Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:15-16
Timestamp: 2024-11-04T14:31:29.664Z
Learning: In `packages/payment-processor/src/payment/prepared-transaction.ts`, for the `IPreparedPrivateTransaction` interface, use `string[]` for the `ops` field since Hinkal's relevant functions accept arrays of `string` as inputs.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-29T09:00:54.169Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:202-209
Timestamp: 2024-10-29T09:00:54.169Z
Learning: In the `packages/payment-processor/src/payment/single-request-proxy.ts` file, within the `payWithEthereumSingleRequestProxy` function, the current error handling is acceptable as per the project's expectations.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:54:04.489Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:9-17
Timestamp: 2024-11-04T20:54:04.489Z
Learning: In the `IPreparedPrivateTransaction` interface within `packages/payment-processor/src/payment/prepared-transaction.ts`, the team prefers concise documentation comments and avoids overly verbose explanations.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-12-18T03:53:54.370Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:38-38
Timestamp: 2024-12-18T03:53:54.370Z
Learning: In `packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts`, mainnet RPC is intentionally used for real on-chain tests as confirmed by MantisClone.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T20:00:33.707Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:4-7
Timestamp: 2024-10-28T20:00:33.707Z
Learning: In TypeScript test files (e.g., `test-deploy-single-request-proxy.ts`), it's acceptable to use `string` types for Ethereum addresses in interfaces (like `FeeProxyAddresses`), as stricter type safety is not necessary.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T21:11:48.524Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:123-184
Timestamp: 2024-10-28T21:11:48.524Z
Learning: When suggesting error handling improvements in `packages/payment-processor/src/payment/single-request-proxy.ts`, avoid recommending try-catch blocks that re-throw errors without additional processing.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-05T14:43:16.298Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol:46-46
Timestamp: 2024-10-05T14:43:16.298Z
Learning: In `packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol`, within the `receive()` function, it's acceptable to approve the entire `balance` to `erc20FeeProxy` because `balance == paymentAmount + feeAmount`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-17T16:00:11.730Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:30-34
Timestamp: 2024-10-17T16:00:11.730Z
Learning: In `packages/smart-contracts/src/contracts/test/UsdtFake.sol`, the code is part of the test harness and not intended for production, so deviations from ERC20 standards are acceptable.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-17T16:00:03.170Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:63-66
Timestamp: 2024-10-17T16:00:03.170Z
Learning: In test harness contracts like `UsdtFake.sol`, which are not meant for production, having an unrestricted `mint` function is acceptable.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, when decoding event data, the team prefers not to include documentation of the event data structure if maintaining it would be difficult.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:53:41.522Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:5-13
Timestamp: 2024-11-04T20:53:41.522Z
Learning: When reviewing the RequestNetwork codebase, avoid suggesting the addition of example usage in documentation if it would make the comments overly verbose, especially for functions like `prepareHinkal` in `packages/payment-processor/src/payment/prepare-hinkal.ts`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:54:11.202Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:20-20
Timestamp: 2024-11-04T20:54:11.202Z
Learning: In `packages/payment-processor/src/payment/prepare-hinkal.ts`, when passing `undefined` parameters to functions like `initProviderAdapter`, it's acceptable not to add comments explaining the `undefined` parameter to avoid overly verbose code.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-22T13:13:26.166Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:0-0
Timestamp: 2024-11-22T13:13:26.166Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, the `FakeLitProtocolProvider` class uses `{}` as the return type for its methods `encrypt` and `decrypt`. Changing the return type to a more specific interface caused issues, so the current return type `{}` should remain as is.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, the team prefers not to store or validate decoded values that are not needed.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-05T14:43:14.816Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:11-15
Timestamp: 2024-10-05T14:43:14.816Z
Learning: In the `EthereumSingleRequestProxy` contract, the state variables `payee`, `paymentReference`, `feeAddress`, `feeAmount`, and `ethereumFeeProxy` should remain public, as they need to be accessed externally.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2025-06-23T09:35:04.263Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1633
File: packages/smart-contracts/src/contracts/ERC20RecurringPaymentProxy.sol:92-133
Timestamp: 2025-06-23T09:35:04.263Z
Learning: In the ERC20RecurringPaymentProxy contract, events were intentionally omitted to save gas costs since the underlying ERC20FeeProxy contract already emits events when payments are processed. This avoids duplicate event emissions while maintaining observability.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-15T07:50:54.734Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:77-78
Timestamp: 2024-10-15T07:50:54.734Z
Learning: In the `receive()` function of the `EthereumSingleRequestProxy` contract (`packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol`), the current error handling for the call to `ethereumFeeProxy` is considered sufficient, and no additional error handling is required.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-28T20:00:53.026Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/src/lib/artifacts/SingleRequestProxyFactory/0.1.0.json:24-124
Timestamp: 2024-10-28T20:00:53.026Z
Learning: In our smart contracts, we should remove the `indexed` keyword from all event parameters except for `paymentReference`, as we use the payment-subgraph for indexing and this reduces gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-15T07:50:58.094Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:22-27
Timestamp: 2024-10-15T07:50:58.094Z
Learning: In the `SingleRequestProxyFactory` contract, the `paymentReference` parameter in events should remain `indexed`, even if removing `indexed` could reduce gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
🧬 Code graph analysis (2)
packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts (1)
packages/smart-contracts/src/lib/ContractArtifact.ts (1)
  • ContractArtifact (36-172)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (4)
packages/types/src/payment-types.ts (6)
  • CommerceEscrowPaymentData (419-431)
  • CommerceEscrowAuthorizeParams (436-449)
  • CommerceEscrowCaptureParams (454-459)
  • CommerceEscrowChargeParams (464-467)
  • CommerceEscrowRefundParams (472-477)
  • CommerceEscrowPaymentState (482-486)
packages/types/src/currency-types.ts (1)
  • EvmChainName (6-35)
packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/index.ts (1)
  • erc20CommerceEscrowWrapperArtifact (7-42)
packages/payment-processor/src/payment/erc20.ts (1)
  • getErc20Allowance (96-104)
🔇 Additional comments (3)
packages/smart-contracts/scripts-create2/constructor-args.ts (1)

102-113: LGTM! Network-specific address resolution correctly implemented.

The constructor args for ERC20CommerceEscrowWrapper now properly resolve network-specific addresses for both the commerce escrow and ERC20 fee proxy dependencies. This follows the established pattern used by other contracts in the file (e.g., ERC20RecurringPaymentProxy, SingleRequestProxyFactory) and resolves the previous hardcoded address concerns.

packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/0.1.0.json (1)

1-1274: ABI artifact looks complete.

This is a generated ABI artifact for the AuthCaptureEscrow contract (version 0.1.0). The ABI includes all expected components: constructor, state-changing functions (authorize, capture, charge, void, refund, reclaim), view functions (getHash, getTokenStore, paymentState, tokenStoreImplementation), events, and custom errors. The structure is well-formed and consistent with Solidity ABI standards.

packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1)

34-60: Critical: Struct is not actually packed as claimed in comments.

The comments claim 6-slot packing (lines 34-40), but Solidity packs struct fields sequentially in declaration order. The current order wastes storage:

Current layout (9+ slots):

  • Slot 0: payer (20) + isActive (1) = 21 bytes
  • Slot 1: merchant (20) alone ← waste
  • Slot 2: amount (12) alone ← waste
  • Slot 3: operator (20) alone ← waste
  • Slot 4: maxAmount (12) alone ← waste
  • Slot 5: token (20) alone ← waste
  • Slot 6: preApprovalExpiry (6) alone ← waste
  • Slot 7: authorizationExpiry (6) alone ← waste
  • Slot 8: refundExpiry (6) alone ← waste
  • Slot 9: commercePaymentHash (32)

Fix: Reorder fields to match comment specification:

 struct PaymentData {
   address payer;
+  bool isActive;
   address merchant;
-  bool isActive;
-  address merchant;
   uint96 amount;
   address operator;
   uint96 maxAmount;
   address token;
   uint48 preApprovalExpiry;
   uint48 authorizationExpiry;
   uint48 refundExpiry;
   bytes32 commercePaymentHash;
 }

This achieves the claimed 6-slot layout and ~45% gas savings on every payment operation.

⛔ Skipped due to learnings
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:9-17
Timestamp: 2024-11-04T20:54:04.489Z
Learning: In the `IPreparedPrivateTransaction` interface within `packages/payment-processor/src/payment/prepared-transaction.ts`, the team prefers concise documentation comments and avoids overly verbose explanations.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, when decoding event data, the team prefers not to include documentation of the event data structure if maintaining it would be difficult.
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:15-16
Timestamp: 2024-11-04T14:31:29.664Z
Learning: In `packages/payment-processor/src/payment/prepared-transaction.ts`, for the `IPreparedPrivateTransaction` interface, use `string[]` for the `ops` field since Hinkal's relevant functions accept arrays of `string` as inputs.
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:104-104
Timestamp: 2024-11-12T16:54:02.702Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, when the smart contract has not changed, event argument names such as `proxyAddress` remain the same, even if variable names in the code are updated to use new terminology like `forwarderAddress`.
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:5-13
Timestamp: 2024-11-04T20:53:41.522Z
Learning: When reviewing the RequestNetwork codebase, avoid suggesting the addition of example usage in documentation if it would make the comments overly verbose, especially for functions like `prepareHinkal` in `packages/payment-processor/src/payment/prepare-hinkal.ts`.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:22-27
Timestamp: 2024-10-15T07:50:58.094Z
Learning: In the `SingleRequestProxyFactory` contract, the `paymentReference` parameter in events should remain `indexed`, even if removing `indexed` could reduce gas costs.

Comment on lines +12 to +25
private: {
address: '0x0000000000000000000000000000000000000000',
creationBlockNumber: 0,
},
// Base Sepolia deployment (same address as mainnet via CREATE2)
sepolia: {
address: '0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff',
creationBlockNumber: 0,
},
// Base Mainnet deployment (same address as sepolia via CREATE2)
base: {
address: '0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff',
creationBlockNumber: 0,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Update creation block numbers after deployment.

All creationBlockNumber values are currently set to 0, which are likely placeholders. After deploying the AuthCaptureEscrow contract on each network, update these values with the actual block numbers where the contracts were deployed. Accurate creation block numbers are important for event indexing and historical data queries.

Run the following script to check if the contracts are already deployed and retrieve their creation blocks:


🏁 Script executed:

#!/bin/bash
# Description: Check if AuthCaptureEscrow is deployed on sepolia and base, and find creation blocks

echo "Checking Sepolia deployment..."
cast code 0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff --rpc-url https://sepolia.base.org 2>/dev/null | head -c 10

echo ""
echo "Checking Base deployment..."
cast code 0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff --rpc-url https://mainnet.base.org 2>/dev/null | head -c 10

Length of output: 59


I need to search the codebase for deployment information about AuthCaptureEscrow to verify the actual deployment status and block numbers.


🏁 Script executed:

#!/bin/bash
# Search for AuthCaptureEscrow deployment scripts and records
echo "=== Searching for AuthCaptureEscrow deployment files ==="
fd -type f "deploy" packages/smart-contracts/deploy --exec basename {} \;

echo ""
echo "=== Searching for AuthCaptureEscrow references with block numbers ==="
rg -n "AuthCaptureEscrow" packages/smart-contracts --type ts --type json -C 2

echo ""
echo "=== Checking for deployment records or transaction data ==="
fd -type f -e json packages/smart-contracts/deploy --exec grep -l "AuthCaptureEscrow" {} \;

echo ""
echo "=== Searching for creationBlockNumber patterns in artifacts ==="
rg -n "0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff" packages/smart-contracts --type ts -C 3

Length of output: 14069


Let me search for any documented deployment block numbers or git history related to this contract:The web search results don't provide specific information about the AuthCaptureEscrow contract's creation blocks. Let me search more specifically for this contract:Let me search for git history or documentation about the AuthCaptureEscrow creation blocks:

Let me search for any deployment records or git history in the codebase:


🏁 Script executed:

#!/bin/bash
# Search for git history related to AuthCaptureEscrow creationBlockNumber updates
echo "=== Searching git log for AuthCaptureEscrow changes ==="
git log --oneline --all -- packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts 2>/dev/null | head -20

echo ""
echo "=== Checking if there's any documentation or README about block numbers ==="
find packages/smart-contracts -name "*.md" -exec grep -l "creationBlockNumber\|creation block\|AuthCaptureEscrow" {} \;

echo ""
echo "=== Full contents of the AuthCaptureEscrow index.ts file ==="
cat packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts

Length of output: 1211


🏁 Script executed:

#!/bin/bash
# Search git history for AuthCaptureEscrow creationBlockNumber
echo "=== Git history for AuthCaptureEscrow artifact file ==="
git log --oneline --all -- packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts 2>/dev/null | head -10

echo ""
echo "=== Check full current artifact file ==="
cat packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts

echo ""
echo "=== Search for any block number references in deployment-related files ==="
rg "creationBlockNumber" packages/smart-contracts -C 2

echo ""
echo "=== Check if there's a deployment history or records file ==="
find packages/smart-contracts -name "*deploy*" -name "*.md" -o -name "*history*" 2>/dev/null

Length of output: 176720


Update creation block numbers after deployment.

All creationBlockNumber values are set to 0, which are placeholders. These must be updated with the actual block numbers where the AuthCaptureEscrow contract was deployed on Base Sepolia and Base Mainnet. Accurate creation block numbers are essential for event indexing and historical data queries.

🤖 Prompt for AI Agents
packages/smart-contracts/src/lib/artifacts/AuthCaptureEscrow/index.ts lines
12-25: the creationBlockNumber fields are left as 0 placeholders; replace the
zeros with the actual block numbers from the deployment transaction receipts for
the Base Sepolia and Base (Mainnet) deployments (retrieve the blockNumber from
the tx receipt or block explorer for the given contract addresses), update the
corresponding creationBlockNumber entries for both `sepolia` and `base`, and
verify the addresses match the deployment before committing.

…rt for ERC20CommerceEscrowWrapper

- Removed direct execution logic from the deploy-erc20-commerce-escrow-wrapper script, emphasizing that it should be run as a Hardhat task.
- Changed the import statement for the AuthCaptureEscrow artifact to use default import syntax for consistency and clarity.
…CommerceEscrowWrapper

- Introduced a new error, `InvalidFeeBps`, to validate fee basis points, ensuring they do not exceed 10000.
- Updated the `_createPaymentInfo` and payment capture functions to include checks for fee basis points.
- Enhanced unit tests to verify the new fee validation logic and ensure proper error handling for invalid fee scenarios.
…s efficiency and clarity

- Updated the PaymentData struct to remove the isActive flag, enhancing gas efficiency and simplifying existence checks by relying on commercePaymentHash.
- Refined event parameters in the ERC20CommerceEscrowWrapper to improve clarity and consistency.
- Enhanced unit tests to verify correct token transfers during payment operations, including authorization, capture, void, and reclaim scenarios.
- Added comprehensive fee calculation tests to ensure accurate handling of various fee percentages during payment processing.
Copy link
Contributor

@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: 4

♻️ Duplicate comments (1)
packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1)

1408-1434: Prefer enum values over magic numbers for AttackType in tests

The reentrancy tests configure attacks with raw numeric IDs (e.g. 2 // CaptureReentry, 3 // VoidReentry, 5 // ReclaimReentry, 6 // RefundReentry). This is brittle: if the enum order in MaliciousReentrant.AttackType ever changes, the tests will silently target the wrong branch.

Since TypeChain is already generating typings for MaliciousReentrant, you can use the enum constants instead of magic numbers:

const AttackType = MaliciousReentrant.AttackType;

await maliciousToken.setupAttack(
  AttackType.CaptureReentry,
  authParams.paymentReference,
  amount.div(4),
  feeBps,
  feeReceiverAddress,
);

This keeps tests aligned with the Solidity enum and avoids future mismatches.

Also applies to: 1468-1493, 1505-1530, 1561-1568, 1645-1651, 1700-1706

🧹 Nitpick comments (1)
packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol (1)

66-68: Unused underlyingToken state variable in test harness

underlyingToken is stored in the constructor but never read anywhere in MaliciousReentrant. Given this is a test-only harness, that’s harmless, but it may trigger compiler warnings.

If you don’t plan to proxy calls to the real underlying token, consider removing this variable (and the constructor parameter) or add a brief comment explaining it’s reserved for potential future use.

Also applies to: 88-91

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ddaf2b5 and 2bc7d83.

📒 Files selected for processing (4)
  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (1 hunks)
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol (1 hunks)
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol (1 hunks)
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (38)
📓 Common learnings
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-12-18T03:53:54.370Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:38-38
Timestamp: 2024-12-18T03:53:54.370Z
Learning: In `packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts`, mainnet RPC is intentionally used for real on-chain tests as confirmed by MantisClone.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-11-06T14:48:18.698Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1484
File: packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts:0-0
Timestamp: 2024-11-06T14:48:18.698Z
Learning: In `packages/advanced-logic/test/extensions/payment-network/any-to-near.test.ts`, when the existing happy path tests are deemed sufficient, additional test cases may not be necessary.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-11-12T17:48:47.072Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:211-219
Timestamp: 2024-11-12T17:48:47.072Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, the error handling logic in `payWithEthereumSingleRequestForwarder` is correct and does not require changes to differentiate between ERC20 and Ethereum SingleRequestForwarder contracts.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-12-04T05:05:19.610Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:0-0
Timestamp: 2024-12-04T05:05:19.610Z
Learning: The function `createRequestForHinkal` in `erc-20-private-payment-hinkal.test.ts` is intended for testing purposes only and should remain in the test directory.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-08T18:24:06.144Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:237-246
Timestamp: 2024-11-08T18:24:06.144Z
Learning: In `packages/payment-processor/test/payment/single-request-proxy.test.ts`, when asserting the `feeProxyUsed` in emitted events from `SingleRequestProxyFactory`, retrieve the `erc20FeeProxy` (or `ethereumFeeProxy`) public variable from the `SingleRequestProxyFactory` contract instead of using `wallet.address`.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-21T09:06:12.938Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:87-119
Timestamp: 2024-11-21T09:06:12.938Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, mocks like `fakeEpkCipherProvider` do not require extensive test coverage for input validation and error handling.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-29T08:02:02.600Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:138-139
Timestamp: 2024-10-29T08:02:02.600Z
Learning: When testing invalid requests in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to use `ts-expect-error` to suppress TypeScript errors when the request intentionally lacks required properties.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-29T08:03:10.463Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:225-228
Timestamp: 2024-10-29T08:03:10.463Z
Learning: In 'packages/payment-processor/test/payment/single-request-proxy.test.ts' (TypeScript), when testing with an invalid proxy address, we should not use the zero address.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-28T20:00:33.707Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:4-7
Timestamp: 2024-10-28T20:00:33.707Z
Learning: In TypeScript test files (e.g., `test-deploy-single-request-proxy.ts`), it's acceptable to use `string` types for Ethereum addresses in interfaces (like `FeeProxyAddresses`), as stricter type safety is not necessary.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-08T18:24:19.095Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:198-206
Timestamp: 2024-11-08T18:24:19.095Z
Learning: In tests for `SingleRequestProxyFactory`, the `feeProxyUsed` in events should be verified by retrieving the `ethereumFeeProxy` public variable from the `SingleRequestProxyFactory` contract, not `wallet.address`.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-12-13T10:00:17.504Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1512
File: packages/integration-test/test/lit-protocol.test.ts:48-50
Timestamp: 2024-12-13T10:00:17.504Z
Learning: In `packages/integration-test/test/lit-protocol.test.ts`, the wallet private key `'0x7b595b2bb732edddc4d4fe758ae528c7a748c40f0f6220f4494e214f15c5bfeb'` is fixed and can be hardcoded in the test file.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
📚 Learning: 2024-11-05T05:33:32.481Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:38-43
Timestamp: 2024-11-05T05:33:32.481Z
Learning: In the RequestNetwork codebase, setup scripts such as `setupSingleRequestProxyFactory.ts` do not include contract existence checks before interacting with contracts, even though scripts like `check-deployer.ts` do include such checks.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-12-09T18:59:04.613Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts:80-99
Timestamp: 2024-12-09T18:59:04.613Z
Learning: In the `RequestNetwork` codebase, payment processor functions such as `payErc20ProxyRequestFromHinkalShieldedAddress` in `packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts` should not include explicit request validation or try/catch blocks, and should rely on the underlying components (like `hinkalObject`) to handle error reporting.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-29T09:00:54.169Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:202-209
Timestamp: 2024-10-29T09:00:54.169Z
Learning: In the `packages/payment-processor/src/payment/single-request-proxy.ts` file, within the `payWithEthereumSingleRequestProxy` function, the current error handling is acceptable as per the project's expectations.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-04T14:32:57.040Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc20-fee-proxy.ts:186-186
Timestamp: 2024-11-04T14:32:57.040Z
Learning: In the `preparePrivateErc20FeeProxyPaymentTransaction` function in `packages/payment-processor/src/payment/erc20-fee-proxy.ts`, we should not make an allowance call on the token contract, as it is not relevant to our use case.

Applied to files:

  • packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-28T20:00:25.780Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:14-32
Timestamp: 2024-10-28T20:00:25.780Z
Learning: In test files, such as `packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts`, extensive error handling and input validation are considered unnecessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-17T18:33:41.124Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/EthereumSingleRequestProxy.test.ts:0-0
Timestamp: 2024-10-17T18:33:41.124Z
Learning: In the `EthereumSingleRequestProxy` contract, the custom reentrancy guard is nearly identical to OpenZeppelin's ReentrancyGuard, except that it allows the first reentrancy call from the `ERC20FeeProxy`. We assume it works correctly without needing further tests.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-10-28T21:11:48.524Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:123-184
Timestamp: 2024-10-28T21:11:48.524Z
Learning: When suggesting error handling improvements in `packages/payment-processor/src/payment/single-request-proxy.ts`, avoid recommending try-catch blocks that re-throw errors without additional processing.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-05T14:43:07.965Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:19-23
Timestamp: 2024-10-05T14:43:07.965Z
Learning: In the `EthereumSingleRequestProxy` contract, a custom reentrancy guard is used instead of OpenZeppelin's `ReentrancyGuard`, with minor edits to allow reentrancy by the `ethereumFeeProxy`.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
📚 Learning: 2024-10-02T05:15:18.868Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1316
File: packages/utils/test/retry.test.ts:149-216
Timestamp: 2024-10-02T05:15:18.868Z
Learning: Developers prefer unrolled loops and explicit comments in test code, particularly in 'retry.test.ts' for the exponential backoff test, to show the number of calls and total elapsed time for retries, rather than refactoring using loops.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-04T12:18:13.888Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/testPayErc20FeeProxyRequestHinkal.ts:19-27
Timestamp: 2024-11-04T12:18:13.888Z
Learning: In the file `packages/usage-examples/src/hinkal/testPayErc20FeeProxyRequestHinkal.ts`, when using `payPrivateErc20FeeProxyRequest`, the returned `tx` is a `RelayerTransaction`, so calling `.wait()` on it is unnecessary.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-10-05T14:43:16.298Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol:46-46
Timestamp: 2024-10-05T14:43:16.298Z
Learning: In `packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol`, within the `receive()` function, it's acceptable to approve the entire `balance` to `erc20FeeProxy` because `balance == paymentAmount + feeAmount`.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2025-06-23T09:35:04.263Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1633
File: packages/smart-contracts/src/contracts/ERC20RecurringPaymentProxy.sol:92-133
Timestamp: 2025-06-23T09:35:04.263Z
Learning: In the ERC20RecurringPaymentProxy contract, events were intentionally omitted to save gas costs since the underlying ERC20FeeProxy contract already emits events when payments are processed. This avoids duplicate event emissions while maintaining observability.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-22T13:13:26.166Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:0-0
Timestamp: 2024-11-22T13:13:26.166Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, the `FakeLitProtocolProvider` class uses `{}` as the return type for its methods `encrypt` and `decrypt`. Changing the return type to a more specific interface caused issues, so the current return type `{}` should remain as is.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-22T13:30:25.703Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:165-205
Timestamp: 2024-11-22T13:30:25.703Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, modifying `storedRawData` in the `FakeLitProtocolProvider` class may break existing functionality, so it should be left as is.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
📚 Learning: 2024-11-12T16:54:02.702Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:104-104
Timestamp: 2024-11-12T16:54:02.702Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, when the smart contract has not changed, event argument names such as `proxyAddress` remain the same, even if variable names in the code are updated to use new terminology like `forwarderAddress`.

Applied to files:

  • packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-05T14:43:14.816Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:11-15
Timestamp: 2024-10-05T14:43:14.816Z
Learning: In the `EthereumSingleRequestProxy` contract, the state variables `payee`, `paymentReference`, `feeAddress`, `feeAmount`, and `ethereumFeeProxy` should remain public, as they need to be accessed externally.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-09-27T11:42:01.062Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:0-0
Timestamp: 2024-09-27T11:42:01.062Z
Learning: In the `createEthereumSingleRequestProxy` function, it's acceptable for `_feeAddress` to be the zero address, as setting the fee address to zero is a common practice. Adding zero address checks is unnecessary and adds extra gas cost.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-15T07:50:54.734Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol:77-78
Timestamp: 2024-10-15T07:50:54.734Z
Learning: In the `receive()` function of the `EthereumSingleRequestProxy` contract (`packages/smart-contracts/src/contracts/EthereumSingleRequestProxy.sol`), the current error handling for the call to `ethereumFeeProxy` is considered sufficient, and no additional error handling is required.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-28T20:00:53.026Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/src/lib/artifacts/SingleRequestProxyFactory/0.1.0.json:24-124
Timestamp: 2024-10-28T20:00:53.026Z
Learning: In our smart contracts, we should remove the `indexed` keyword from all event parameters except for `paymentReference`, as we use the payment-subgraph for indexing and this reduces gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-15T07:50:58.094Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:22-27
Timestamp: 2024-10-15T07:50:58.094Z
Learning: In the `SingleRequestProxyFactory` contract, the `paymentReference` parameter in events should remain `indexed`, even if removing `indexed` could reduce gas costs.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, when decoding event data, the team prefers not to include documentation of the event data structure if maintaining it would be difficult.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-11-04T20:53:41.522Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:5-13
Timestamp: 2024-11-04T20:53:41.522Z
Learning: When reviewing the RequestNetwork codebase, avoid suggesting the addition of example usage in documentation if it would make the comments overly verbose, especially for functions like `prepareHinkal` in `packages/payment-processor/src/payment/prepare-hinkal.ts`.

Applied to files:

  • packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol
📚 Learning: 2024-10-17T16:00:11.730Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:30-34
Timestamp: 2024-10-17T16:00:11.730Z
Learning: In `packages/smart-contracts/src/contracts/test/UsdtFake.sol`, the code is part of the test harness and not intended for production, so deviations from ERC20 standards are acceptable.

Applied to files:

  • packages/smart-contracts/src/contracts/test/MaliciousReentrant.sol
🧬 Code graph analysis (1)
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (2)
packages/types/src/currency-types.ts (1)
  • EvmChainName (6-35)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (23)
  • AuthorizePaymentParams (9-9)
  • CapturePaymentParams (10-10)
  • ChargePaymentParams (11-11)
  • RefundPaymentParams (12-12)
  • getCommerceEscrowWrapperAddress (22-30)
  • encodeSetCommerceEscrowAllowance (70-90)
  • getPayerCommerceEscrowAllowance (42-58)
  • encodeAuthorizePayment (105-136)
  • encodeCapturePayment (147-163)
  • encodeVoidPayment (174-185)
  • encodeChargePayment (200-233)
  • encodeReclaimPayment (244-255)
  • encodeRefundPayment (266-282)
  • authorizePayment (293-317)
  • capturePayment (328-352)
  • voidPayment (363-387)
  • chargePayment (398-422)
  • reclaimPayment (433-457)
  • refundPayment (468-492)
  • getPaymentData (503-529)
  • getPaymentState (540-553)
  • canCapture (564-575)
  • canVoid (586-597)
🔇 Additional comments (1)
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts (1)

430-628: Excellent edge case coverage.

The parameter validation and edge case testing is exceptionally comprehensive, covering minimum/maximum values, zero values, boundary conditions, special patterns, different token decimals, and time-based scenarios. This thorough approach will help catch potential issues early and documents expected behavior well.

Also applies to: 1104-1321

Comment on lines +136 to +155
it('should handle zero amount', () => {
const mockAddress = '0x1234567890123456789012345678901234567890';
jest
.spyOn(
require('../../src/payment/erc20-commerce-escrow-wrapper'),
'getCommerceEscrowWrapperAddress',
)
.mockReturnValue(mockAddress);

const transactions = encodeSetCommerceEscrowAllowance({
tokenAddress: erc20ContractAddress,
amount: '0',
provider,
network,
isUSDT: false,
});

expect(transactions).toHaveLength(1);
expect(transactions[0].to).toBe(erc20ContractAddress);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove the non-existent isUSDT parameter.

The encodeSetCommerceEscrowAllowance function does not accept an isUSDT parameter according to the implementation. This parameter is being passed in these tests but will be ignored, which can cause confusion and mislead future maintainers.

Apply this diff to remove the unused parameter:

     const transactions = encodeSetCommerceEscrowAllowance({
       tokenAddress: erc20ContractAddress,
       amount: '0',
       provider,
       network,
-      isUSDT: false,
     });

Apply similar changes to lines 173, 195, and 209.

Also applies to: 157-178, 180-200, 202-212

🤖 Prompt for AI Agents
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
around lines 136-155 (and similarly update blocks at 157-178, 180-200, 202-212):
the test calls encodeSetCommerceEscrowAllowance with a non-existent isUSDT
parameter; remove the isUSDT property from the argument objects in these test
cases so the call matches the actual function signature, keep all other keys
(tokenAddress, amount, provider, network) unchanged, and run tests to confirm no
other references to isUSDT remain in this test file.

Comment on lines +216 to +248
it('should call getErc20Allowance with correct parameters', async () => {
// Mock getErc20Allowance to avoid actual blockchain calls
const mockGetErc20Allowance = jest
.fn()
.mockResolvedValue({ toString: () => '1000000000000000000' });

// Mock the getErc20Allowance function
jest.doMock('../../src/payment/erc20', () => ({
getErc20Allowance: mockGetErc20Allowance,
}));

// Clear the module cache and re-import
jest.resetModules();
const {
getPayerCommerceEscrowAllowance,
} = require('../../src/payment/erc20-commerce-escrow-wrapper');

const result = await getPayerCommerceEscrowAllowance({
payerAddress: wallet.address,
tokenAddress: erc20ContractAddress,
provider,
network,
});

expect(result).toBe('1000000000000000000');
expect(mockGetErc20Allowance).toHaveBeenCalledWith(
wallet.address,
'0x1234567890123456789012345678901234567890', // wrapper address
provider,
erc20ContractAddress,
);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the unreliable mock pattern.

This test uses jest.doMock and jest.resetModules() after the module has already been imported at the top of the file. This pattern is unreliable because the module cache may not be properly cleared, potentially causing flaky tests.

Consider using jest.spyOn to mock the getErc20Allowance function directly instead:

   it('should call getErc20Allowance with correct parameters', async () => {
-    // Mock getErc20Allowance to avoid actual blockchain calls
-    const mockGetErc20Allowance = jest
-      .fn()
-      .mockResolvedValue({ toString: () => '1000000000000000000' });
-
-    // Mock the getErc20Allowance function
-    jest.doMock('../../src/payment/erc20', () => ({
-      getErc20Allowance: mockGetErc20Allowance,
-    }));
-
-    // Clear the module cache and re-import
-    jest.resetModules();
-    const {
-      getPayerCommerceEscrowAllowance,
-    } = require('../../src/payment/erc20-commerce-escrow-wrapper');
+    const { getErc20Allowance } = require('../../src/payment/erc20');
+    const mockGetErc20Allowance = jest
+      .spyOn(require('../../src/payment/erc20'), 'getErc20Allowance')
+      .mockResolvedValue({ toString: () => '1000000000000000000' });
 
     const result = await getPayerCommerceEscrowAllowance({
       payerAddress: wallet.address,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
packages/payment-processor/test/payment/erc20-commerce-escrow-wrapper.test.ts
lines 216-248: the test currently uses jest.doMock and jest.resetModules after
the module has been imported which is unreliable; instead import the real
modules and replace the doMock/resetModules pattern with jest.spyOn on the
'../../src/payment/erc20' module's getErc20Allowance function (or import the
erc20 module and call jest.spyOn(erc20Module,
'getErc20Allowance').mockResolvedValue(...)) before invoking
getPayerCommerceEscrowAllowance, remove the doMock/resetModules calls, assert
the same arguments/return, and ensure you restore the spy after the test
(mockRestore) to avoid test pollution.

Comment on lines +33 to +43
/// @notice Internal payment data structure
/// @dev Struct packing optimizes storage from 11 slots to 5 slots (~55% gas savings)
/// Slot 0: payer (20 bytes)
/// Slot 1: merchant (20 bytes) + amount (12 bytes)
/// Slot 2: operator (20 bytes) + maxAmount (12 bytes)
/// Slot 3: token (20 bytes) + preApprovalExpiry (6 bytes) + authorizationExpiry (6 bytes)
/// Slot 4: refundExpiry (6 bytes)
/// Slot 5: commercePaymentHash (32 bytes)
/// @dev Payment existence is determined by commercePaymentHash != bytes32(0)
/// This approach delegates to the Commerce Escrow's state tracking without external calls,
/// maintaining gas efficiency while avoiding state synchronization issues.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix PaymentData struct slot-count comment

The comment says struct packing reduces storage “to 5 slots”, but the subsequent bullets list Slot 0 through Slot 5 (6 slots), and the fields indeed occupy 6 storage slots (payer, merchant+amount, operator+maxAmount, token+two expiries, refundExpiry, commercePaymentHash).

Recommend updating the comment to reflect the correct slot count (6) so it matches the actual layout and avoids confusion during future gas-cost analysis.

🤖 Prompt for AI Agents
In packages/smart-contracts/src/contracts/ERC20CommerceEscrowWrapper.sol around
lines 33 to 43, the comment incorrectly states struct packing reduces storage
"to 5 slots" while the bullet list shows Slot 0 through Slot 5 (6 slots); update
the comment to say "6 slots" (and adjust any parenthetical phrasing if needed)
so the slot-count matches the listed layout and avoids confusion during gas-cost
analysis.

Comment on lines +1395 to +1463
describe('Reentrancy Protection', () => {
let maliciousToken: MaliciousReentrant;

beforeEach(async () => {
// Deploy malicious token that will attempt reentrancy attacks
maliciousToken = await new MaliciousReentrant__factory(owner).deploy(
wrapper.address,
testERC20.address,
);
});

describe('capturePayment reentrancy', () => {
it('should prevent reentrancy attack on capturePayment', async () => {
const authParams = {
paymentReference: getUniquePaymentReference(),
payer: payerAddress,
merchant: merchantAddress,
operator: operatorAddress,
token: maliciousToken.address,
amount,
maxAmount,
preApprovalExpiry,
authorizationExpiry,
refundExpiry,
tokenCollector: tokenCollectorAddress,
collectorData: '0x',
};

// Authorize payment with malicious token
await wrapper.authorizePayment(authParams);

// Setup the attack: when the wrapper calls token.approve() during capture,
// the malicious token will attempt to call capturePayment again
await maliciousToken.setupAttack(
2, // CaptureReentry (enum value is 2, not 1)
authParams.paymentReference,
amount.div(4),
feeBps,
feeReceiverAddress,
);

// Attempt to capture - the malicious token will try to reenter during the approve call
// The transaction should succeed, but the attack should fail (caught by try-catch)
const tx = await wrapper
.connect(operator)
.capturePayment(authParams.paymentReference, amount.div(2), feeBps, feeReceiverAddress);

const receipt = await tx.wait();

// Check if attack was attempted and failed
const attackEvent = receipt.events?.find(
(e) =>
e.address === maliciousToken.address &&
e.topics[0] === maliciousToken.interface.getEventTopic('AttackAttempted'),
);

// If attack was attempted, verify it failed (success = false)
if (attackEvent) {
const decoded = maliciousToken.interface.decodeEventLog(
'AttackAttempted',
attackEvent.data,
attackEvent.topics,
);
expect(decoded.success).to.be.false;
}

// The capture should still succeed (protected by reentrancy guard)
expect(tx).to.emit(wrapper, 'PaymentCaptured');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Strengthen reentrancy tests: missing await on .to.emit and optional attack assertion

In the reentrancy suites (capturePayment, chargePayment, and cross‑function reentrancy), there are two issues:

  1. expect(tx).to.emit(...) is used without await (e.g. Line 1462, 1621, 1678, 1733). In Hardhat/Chai, to.emit returns a promise; if you neither await nor return it, the assertion may never be observed by Mocha, so these tests can pass even when the event is not emitted.

  2. The AttackAttempted event is treated as optional:

const attackEvent = receipt.events?.find(/* ... */);

// If attack was attempted, verify it failed (success = false)
if (attackEvent) {
  // ...
  expect(decoded.success).to.be.false;
}

If the reentrancy hook stops firing (e.g. wiring changes, enum regression), attackEvent becomes undefined and the test still passes, which weakens security coverage.

Suggestions:

  • Add await in all these places so event expectations are enforced:
await expect(tx).to.emit(wrapper, 'PaymentCaptured');
// ...
await expect(tx).to.emit(wrapper, 'PaymentCharged');
  • Also assert that the attack was actually attempted, not just optionally checked:
expect(attackEvent, 'AttackAttempted should be emitted').to.not.be.undefined;
const decoded = maliciousToken.interface.decodeEventLog(/* ... */);
expect(decoded.success).to.be.false;

This ensures each reentrancy test both (a) triggers the malicious reentry path and (b) verifies the guard blocked it.

Also applies to: 1576-1622, 1625-1735

🤖 Prompt for AI Agents
In packages/smart-contracts/test/contracts/ERC20CommerceEscrowWrapper.test.ts
around lines 1395-1463 (and similarly at 1576-1622, 1625-1735), the tests use
expect(tx).to.emit(...) without awaiting the returned promise and treat the
AttackAttempted event as optional; update each event assertion to await the
expect(...) promise (e.g., await expect(tx).to.emit(...)) so Mocha observes
failures, and change the optional attackEvent check to assert the event exists
before decoding (e.g., expect(attackEvent, 'AttackAttempted should be
emitted').to.not.be.undefined; then decode and assert decoded.success is false)
to ensure the reentrancy attack path was exercised and blocked.

…optimizer settings

- Modified the Solidity configuration to include optimizer settings, enabling optimization with 200 runs for improved contract performance.
Copy link
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2bc7d83 and 8e19768.

📒 Files selected for processing (1)
  • packages/smart-contracts/hardhat.config.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-11T16:10:26.692Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1486
File: packages/smart-contracts/deploy/deploy-zk-single-request-proxy.ts:1-24
Timestamp: 2024-11-11T16:10:26.692Z
Learning: The team prefers to maintain individual deployment scripts for each network in `packages/smart-contracts/deploy`, rather than consolidating them into a unified script.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-10-28T20:02:48.835Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:29-29
Timestamp: 2024-10-28T20:02:48.835Z
Learning: In test deployment scripts (e.g., files like 'test-deploy-*.ts' in 'packages/smart-contracts/scripts'), it's acceptable to use `console.log` for logging.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-05T05:33:36.189Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:26-28
Timestamp: 2024-11-05T05:33:36.189Z
Learning: In the `requestNetwork` project's TypeScript setup scripts located in `packages/smart-contracts/scripts-create2/contract-setup`, `Promise.all` is used for asynchronous network setup tasks to maintain consistency across scripts.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-05T05:33:36.551Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:30-36
Timestamp: 2024-11-05T05:33:36.551Z
Learning: In the RequestNetwork project, admin scripts like `setupSingleRequestProxyFactory.ts` in `packages/smart-contracts/scripts-create2/contract-setup/` do not require extensive error checking.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-04T12:18:18.615Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/package.json:42-42
Timestamp: 2024-11-04T12:18:18.615Z
Learning: In the RequestNetwork project, the `dotenv` package version is maintained at `10.0.0` across packages, including `packages/smart-contracts/package.json`, to ensure consistency.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-05T16:58:18.471Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/payment-detection/test/provider.test.ts:25-25
Timestamp: 2024-11-05T16:58:18.471Z
Learning: In `provider.test.ts`, when testing `getDefaultProvider`, we use a chain that Infura supports but is not in our own RPC list (such as `maticmum`) to ensure that the function correctly falls back to `InfuraProvider`.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-11-04T14:30:34.835Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/hinkalRequestData.ts:5-6
Timestamp: 2024-11-04T14:30:34.835Z
Learning: In `packages/usage-examples/src/hinkal/hinkalRequestData.ts`, it's acceptable to hardcode the USDC contract address without creating a mapping of USDC assets on specific networks.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
📚 Learning: 2024-12-04T05:01:13.722Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/usage-examples/src/hinkal/hinkalRequestData.ts:0-0
Timestamp: 2024-12-04T05:01:13.722Z
Learning: In `packages/usage-examples/src/hinkal/hinkalRequestData.ts`, when integrating Hinkal, it's acceptable for the network to be set to 'base' as the payment chain while using the Sepolia gateway URL ('https://sepolia.gateway.request.network') as the request storage chain.

Applied to files:

  • packages/smart-contracts/hardhat.config.ts
🧬 Code graph analysis (1)
packages/smart-contracts/hardhat.config.ts (1)
packages/smart-contracts/scripts/deploy-erc20-commerce-escrow-wrapper.ts (1)
  • deployERC20CommerceEscrowWrapper (22-90)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (4)
packages/smart-contracts/hardhat.config.ts (4)

25-25: LGTM!

The import statement is correct and the function is properly used in the new deployment task below.


216-220: LGTM!

The Base Sepolia network configuration is correct with the proper chain ID (84532) and official RPC URL.


281-288: LGTM!

The Base Sepolia Etherscan configuration is correct with proper API and browser URLs for contract verification.


72-80: Verify deployment status before enabling Solidity optimizer—this is a breaking change for CREATE2 contracts.

The change from solidity: '0.8.9' (optimizer disabled by default) to the object configuration with optimizer: { enabled: true, runs: 200 } will modify the bytecode of all compiled contracts. This directly breaks CREATE2 deployment address calculations:

  1. Address computation depends on bytecode: compute-one-address.ts uses keccak256(initcode.data) to calculate CREATE2 addresses. Different bytecode → different hash → different addresses.
  2. Setup scripts expect known addresses: setupSingleRequestProxyFactory.ts and others retrieve deployed contract addresses via artifact.getAddress(network). If contracts are already deployed at old addresses (computed with optimizer disabled), the new deployment will target different addresses.
  3. Verification will fail: The verify.ts script recomputes addresses for on-chain verification. With the new optimizer settings, computed addresses won't match existing on-chain deployments.

Action required:

  • Confirm whether contracts are already deployed on any network with the old compilation settings.
  • If yes: recompute and validate all deployment addresses, or redeploy with the new settings.
  • If this is a fresh deployment (no prior deployments), proceed but document the optimizer configuration for future consistency.

Comment on lines +418 to +429
task(
'deploy-erc20-commerce-escrow-wrapper',
'Deploy ERC20CommerceEscrowWrapper and its dependencies',
)
.addFlag('dryRun', 'to prevent any deployment')
.addFlag('force', 'to force re-deployment')
.setAction(async (args, hre) => {
args.force = args.force ?? false;
args.dryRun = args.dryRun ?? false;
args.simulate = args.dryRun;
await deployERC20CommerceEscrowWrapper(args, hre);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add the DEPLOYER_KEY_GUARD check for security.

The new deployment task is missing the DEPLOYER_KEY_GUARD check that other deployment tasks use (e.g., line 349 in deploy-live-storage). This guard prevents accidental usage of the deployer master key, which is a critical security measure.

Apply this diff to add the security check:

   .addFlag('dryRun', 'to prevent any deployment')
   .addFlag('force', 'to force re-deployment')
   .setAction(async (args, hre) => {
     args.force = args.force ?? false;
     args.dryRun = args.dryRun ?? false;
     args.simulate = args.dryRun;
+    await hre.run(DEPLOYER_KEY_GUARD);
     await deployERC20CommerceEscrowWrapper(args, hre);
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
task(
'deploy-erc20-commerce-escrow-wrapper',
'Deploy ERC20CommerceEscrowWrapper and its dependencies',
)
.addFlag('dryRun', 'to prevent any deployment')
.addFlag('force', 'to force re-deployment')
.setAction(async (args, hre) => {
args.force = args.force ?? false;
args.dryRun = args.dryRun ?? false;
args.simulate = args.dryRun;
await deployERC20CommerceEscrowWrapper(args, hre);
});
task(
'deploy-erc20-commerce-escrow-wrapper',
'Deploy ERC20CommerceEscrowWrapper and its dependencies',
)
.addFlag('dryRun', 'to prevent any deployment')
.addFlag('force', 'to force re-deployment')
.setAction(async (args, hre) => {
args.force = args.force ?? false;
args.dryRun = args.dryRun ?? false;
args.simulate = args.dryRun;
await hre.run(DEPLOYER_KEY_GUARD);
await deployERC20CommerceEscrowWrapper(args, hre);
});
🤖 Prompt for AI Agents
packages/smart-contracts/hardhat.config.ts around lines 418 to 429: the new
'deploy-erc20-commerce-escrow-wrapper' task lacks the DEPLOYER_KEY_GUARD call
used by other deployment tasks to prevent accidental use of the deployer master
key; add the same guard invocation (await DEPLOYER_KEY_GUARD(...)) immediately
after normalizing args and before calling deployERC20CommerceEscrowWrapper,
using the same argument signature (args, hre) as in the other tasks so the task
aborts when the guard triggers.

… from commercePaymentHash

- Modified the getPaymentData function to determine the isActive status based on the commercePaymentHash, simplifying the logic.
- Adjusted the return values to directly use rawData for expiry fields, enhancing clarity and consistency in the data structure.
Copy link
Contributor

@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

🧹 Nitpick comments (1)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1)

503-532: Consider explicit conversion of timestamp fields to numbers.

Lines 526-528 assign preApprovalExpiry, authorizationExpiry, and refundExpiry directly from rawData. The CommerceEscrowPaymentData interface types these as number, but ethers v5 typically returns uint256 fields as BigNumber objects. While implicit conversion may work in some contexts, explicit .toNumber() conversion ensures type safety and clarity.

Apply this diff to add explicit conversions:

   return {
     payer: rawData.payer,
     merchant: rawData.merchant,
     operator: rawData.operator,
     token: rawData.token,
     amount: rawData.amount,
     maxAmount: rawData.maxAmount,
-    preApprovalExpiry: rawData.preApprovalExpiry,
-    authorizationExpiry: rawData.authorizationExpiry,
-    refundExpiry: rawData.refundExpiry,
+    preApprovalExpiry: rawData.preApprovalExpiry.toNumber(),
+    authorizationExpiry: rawData.authorizationExpiry.toNumber(),
+    refundExpiry: rawData.refundExpiry.toNumber(),
     commercePaymentHash: rawData.commercePaymentHash,
     isActive,
   };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e19768 and c30f884.

📒 Files selected for processing (1)
  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (27)
📓 Common learnings
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.
📚 Learning: 2024-11-12T17:48:47.072Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:211-219
Timestamp: 2024-11-12T17:48:47.072Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, the error handling logic in `payWithEthereumSingleRequestForwarder` is correct and does not require changes to differentiate between ERC20 and Ethereum SingleRequestForwarder contracts.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-12T16:54:02.702Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1488
File: packages/payment-processor/src/payment/single-request-forwarder.ts:104-104
Timestamp: 2024-11-12T16:54:02.702Z
Learning: In `packages/payment-processor/src/payment/single-request-forwarder.ts`, when the smart contract has not changed, event argument names such as `proxyAddress` remain the same, even if variable names in the code are updated to use new terminology like `forwarderAddress`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-12-09T18:59:04.613Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts:80-99
Timestamp: 2024-12-09T18:59:04.613Z
Learning: In the `RequestNetwork` codebase, payment processor functions such as `payErc20ProxyRequestFromHinkalShieldedAddress` in `packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts` should not include explicit request validation or try/catch blocks, and should rely on the underlying components (like `hinkalObject`) to handle error reporting.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-05T16:53:05.280Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1481
File: packages/integration-test/test/scheduled/erc20-proxy.test.ts:0-0
Timestamp: 2024-11-05T16:53:05.280Z
Learning: In `packages/integration-test/test/scheduled/erc20-proxy.test.ts`, when upgrading dependencies like `ethers`, additional error handling test cases for contract interactions and provider errors may not be necessary.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T14:31:29.664Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:15-16
Timestamp: 2024-11-04T14:31:29.664Z
Learning: In `packages/payment-processor/src/payment/prepared-transaction.ts`, for the `IPreparedPrivateTransaction` interface, use `string[]` for the `ops` field since Hinkal's relevant functions accept arrays of `string` as inputs.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-29T09:00:54.169Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:202-209
Timestamp: 2024-10-29T09:00:54.169Z
Learning: In the `packages/payment-processor/src/payment/single-request-proxy.ts` file, within the `payWithEthereumSingleRequestProxy` function, the current error handling is acceptable as per the project's expectations.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-12-18T03:53:54.370Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:38-38
Timestamp: 2024-12-18T03:53:54.370Z
Learning: In `packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts`, mainnet RPC is intentionally used for real on-chain tests as confirmed by MantisClone.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:54:04.489Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepared-transaction.ts:9-17
Timestamp: 2024-11-04T20:54:04.489Z
Learning: In the `IPreparedPrivateTransaction` interface within `packages/payment-processor/src/payment/prepared-transaction.ts`, the team prefers concise documentation comments and avoids overly verbose explanations.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T16:03:33.215Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:251-270
Timestamp: 2024-10-28T16:03:33.215Z
Learning: When testing the payment-processor module, specifically in `packages/payment-processor/test/payment/single-request-proxy.test.ts`, it's acceptable to omit tests for partial payments if they have already been covered at the smart-contract level.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T18:24:06.144Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:237-246
Timestamp: 2024-11-08T18:24:06.144Z
Learning: In `packages/payment-processor/test/payment/single-request-proxy.test.ts`, when asserting the `feeProxyUsed` in emitted events from `SingleRequestProxyFactory`, retrieve the `erc20FeeProxy` (or `ethereumFeeProxy`) public variable from the `SingleRequestProxyFactory` contract instead of using `wallet.address`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T20:00:33.707Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/smart-contracts/scripts/test-deploy-single-request-proxy.ts:4-7
Timestamp: 2024-10-28T20:00:33.707Z
Learning: In TypeScript test files (e.g., `test-deploy-single-request-proxy.ts`), it's acceptable to use `string` types for Ethereum addresses in interfaces (like `FeeProxyAddresses`), as stricter type safety is not necessary.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-05T05:33:32.481Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1478
File: packages/smart-contracts/scripts-create2/contract-setup/setupSingleRequestProxyFactory.ts:38-43
Timestamp: 2024-11-05T05:33:32.481Z
Learning: In the RequestNetwork codebase, setup scripts such as `setupSingleRequestProxyFactory.ts` do not include contract existence checks before interacting with contracts, even though scripts like `check-deployer.ts` do include such checks.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T21:11:48.524Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:123-184
Timestamp: 2024-10-28T21:11:48.524Z
Learning: When suggesting error handling improvements in `packages/payment-processor/src/payment/single-request-proxy.ts`, avoid recommending try-catch blocks that re-throw errors without additional processing.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-28T15:52:05.032Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/src/payment/single-request-proxy.ts:156-160
Timestamp: 2024-10-28T15:52:05.032Z
Learning: In the `payRequestWithSingleRequestProxy` function of `single-request-proxy.ts`, failing to retrieve `tokenAddress()` is expected for `EthereumSingleRequestProxy` contracts and is not an error.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-29T08:03:10.463Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1474
File: packages/payment-processor/test/payment/single-request-proxy.test.ts:225-228
Timestamp: 2024-10-29T08:03:10.463Z
Learning: In 'packages/payment-processor/test/payment/single-request-proxy.test.ts' (TypeScript), when testing with an invalid proxy address, we should not use the zero address.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-05T14:43:16.298Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol:46-46
Timestamp: 2024-10-05T14:43:16.298Z
Learning: In `packages/smart-contracts/src/contracts/ERC20SingleRequestProxy.sol`, within the `receive()` function, it's acceptable to approve the entire `balance` to `erc20FeeProxy` because `balance == paymentAmount + feeAmount`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T14:32:57.040Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/erc20-fee-proxy.ts:186-186
Timestamp: 2024-11-04T14:32:57.040Z
Learning: In the `preparePrivateErc20FeeProxyPaymentTransaction` function in `packages/payment-processor/src/payment/erc20-fee-proxy.ts`, we should not make an allowance call on the token contract, as it is not relevant to our use case.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-17T16:00:11.730Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:30-34
Timestamp: 2024-10-17T16:00:11.730Z
Learning: In `packages/smart-contracts/src/contracts/test/UsdtFake.sol`, the code is part of the test harness and not intended for production, so deviations from ERC20 standards are acceptable.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-09-27T11:42:01.062Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/SingleRequestProxyFactory.sol:0-0
Timestamp: 2024-09-27T11:42:01.062Z
Learning: In the `createEthereumSingleRequestProxy` function, it's acceptable for `_feeAddress` to be the zero address, as setting the fee address to zero is a common practice. Adding zero address checks is unnecessary and adds extra gas cost.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-17T16:00:03.170Z
Learnt from: aimensahnoun
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/src/contracts/test/UsdtFake.sol:63-66
Timestamp: 2024-10-17T16:00:03.170Z
Learning: In test harness contracts like `UsdtFake.sol`, which are not meant for production, having an unrestricted `mint` function is acceptable.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-10-17T18:30:55.410Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1453
File: packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts:150-152
Timestamp: 2024-10-17T18:30:55.410Z
Learning: In `packages/smart-contracts/test/contracts/ERC20SingleRequestProxy.test.ts`, the skipped test `'should process a partial payment correctly'` exists intentionally to show that partial payments are supported without duplicating previous happy-path tests.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, when decoding event data, the team prefers not to include documentation of the event data structure if maintaining it would be difficult.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:53:41.522Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:5-13
Timestamp: 2024-11-04T20:53:41.522Z
Learning: When reviewing the RequestNetwork codebase, avoid suggesting the addition of example usage in documentation if it would make the comments overly verbose, especially for functions like `prepareHinkal` in `packages/payment-processor/src/payment/prepare-hinkal.ts`.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-04T20:54:11.202Z
Learnt from: giorgi-kiknavelidze
Repo: RequestNetwork/requestNetwork PR: 1482
File: packages/payment-processor/src/payment/prepare-hinkal.ts:20-20
Timestamp: 2024-11-04T20:54:11.202Z
Learning: In `packages/payment-processor/src/payment/prepare-hinkal.ts`, when passing `undefined` parameters to functions like `initProviderAdapter`, it's acceptable not to add comments explaining the `undefined` parameter to avoid overly verbose code.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-22T13:13:26.166Z
Learnt from: rodrigopavezi
Repo: RequestNetwork/requestNetwork PR: 1475
File: packages/transaction-manager/test/unit/utils/test-data.ts:0-0
Timestamp: 2024-11-22T13:13:26.166Z
Learning: In `packages/transaction-manager/test/unit/utils/test-data.ts`, the `FakeLitProtocolProvider` class uses `{}` as the return type for its methods `encrypt` and `decrypt`. Changing the return type to a more specific interface caused issues, so the current return type `{}` should remain as is.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
📚 Learning: 2024-11-08T20:01:10.313Z
Learnt from: MantisClone
Repo: RequestNetwork/requestNetwork PR: 1487
File: packages/payment-processor/src/payment/single-request-proxy.ts:0-0
Timestamp: 2024-11-08T20:01:10.313Z
Learning: In `packages/payment-processor/src/payment/single-request-proxy.ts`, the team prefers not to store or validate decoded values that are not needed.

Applied to files:

  • packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts
🧬 Code graph analysis (1)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (4)
packages/types/src/payment-types.ts (6)
  • CommerceEscrowPaymentData (419-431)
  • CommerceEscrowAuthorizeParams (436-449)
  • CommerceEscrowCaptureParams (454-459)
  • CommerceEscrowChargeParams (464-467)
  • CommerceEscrowRefundParams (472-477)
  • CommerceEscrowPaymentState (482-486)
packages/types/src/currency-types.ts (1)
  • EvmChainName (6-35)
packages/smart-contracts/src/lib/artifacts/ERC20CommerceEscrowWrapper/index.ts (1)
  • erc20CommerceEscrowWrapperArtifact (7-42)
packages/payment-processor/src/payment/erc20.ts (1)
  • getErc20Allowance (96-104)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (2)
packages/payment-processor/src/payment/erc20-commerce-escrow-wrapper.ts (2)

1-13: LGTM! Clean imports and convenient type re-exports.

The imports are well-organized, and the type re-exports provide a convenient API surface for consumers of this module.


567-600: LGTM! Clean query helpers for payment capabilities.

Both canCapture and canVoid follow a simple, consistent pattern for querying payment state from the contract.

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.

Checkout Commerce Wrapper Smart Contract

5 participants