Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: payment processor #5

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

feat: payment processor #5

wants to merge 11 commits into from

Conversation

hey-ewan
Copy link
Member

@hey-ewan hey-ewan commented Feb 9, 2025

this is the initial version of our payment system designed to add cost coverage of transactions to the api

Summary by CodeRabbit

  • New Features

    • Added new environment configuration options.
    • Enhanced the registration system with improved intellectual property licence management and robust financial transaction tracking.
    • Introduced a payment module that enables users to deposit funds, monitor balances, and estimate fees.
  • Chores

    • Upgraded several dependency versions to ensure improved performance and security.

Copy link

coderabbitai bot commented Feb 23, 2025

Walkthrough

This pull request introduces several updates across the repository. Two new environment variables have been added to the environment example file. Dependency versions have been bumped in the package configuration. The ForgeRegistry smart contract now inherits additional modules and includes new function parameters, events, structs, and custom errors to support licensing, royalty management, and payment handling. A new abstract contract, ForgeStorage, has been added to maintain user-related data. Additionally, a new Rust package named "payment" has been introduced with its Cargo configuration, new public function stubs, and a test module.

Changes

File(s) Summary of Changes
.env.example Added two new environment variables: OTHENTIC_BOOTSTRAP_SEED and OTHENTIC_BOOTSTRAP_ID.
execution/contracts/package.json Updated dependency versions for @openzeppelin/contracts, @openzeppelin/contracts-upgradeable, @story-protocol/protocol-core, and @story-protocol/protocol-periphery.
execution/contracts/src/ForgeRegistry.sol
execution/contracts/src/ForgeStorage.sol
Enhanced the ForgeRegistry contract by adding new inheritance (including ReentrancyGuardUpgradeable and ForgeStorage), updated function signatures, new events, structs, and custom errors for licensing and payment operations; introduced the new abstract contract ForgeStorage to manage user data.
execution/crates/payment/Cargo.toml
execution/crates/payment/src/lib.rs
Introduced a new Rust package "payment" with its Cargo configuration, declared library details, added required dependencies, and defined three new public function stubs (deposit_to_forge, check_balance_on_forge, and estimate_fee), along with a test module.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant FR as ForgeRegistry
    participant LM as LicensingModule
    U->>FR: Initialise contract (ipAssetRegistry, workflows, licensing, etc.)
    Note right of FR: Sets licensing, royalty, and batcher configurations
    U->>FR: Call register(receiver, IPMetadata, appId, submitter)
    FR->>FR: Validate parameters and update state
    FR->>LM: Attach licensing terms
    FR-->>U: Emit events (e.g. PaymentReceived, FundsWithdrawn)
Loading

Poem

I'm a rabbit with a code delight,
Hop-ping through functions day and night.
New seeds of variables sprout with cheer,
Dependencies and contracts now crystal clear.
I bounce and celebrate each refined line,
With CodeRabbit magic so beautifully fine!
🐰✨


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (6)
execution/contracts/src/ForgeRegistry.sol (3)

16-17: Remove duplicate import.

Line 16 and line 17 import the same contract RoyaltyPolicyLAP. Please remove one of the imports to avoid confusion.

- import {RoyaltyPolicyLAP} from "@storyprotocol/core/modules/royalty/policies/LAP/RoyaltyPolicyLAP.sol";

122-126: Minimise repeated ownership initialisation.

You are calling __Ownable_init(owner) and _transferOwnership(owner) in the same function. Typically, __Ownable_init(owner) is sufficient to set up ownership. Re-check if the second call to _transferOwnership(owner) is needed.


281-299: Emitted event BalanceLocked is confusing during withdraw.

You emit BalanceLocked(msg.sender) on line 296 within the withdraw() function after resetting unlockBlockTime. This may cause confusion, as the user is withdrawing rather than explicitly re-locking funds. Consider using a more specific event name or clarifying the rationale.

execution/crates/payment/src/lib.rs (2)

1-5: These public functions currently have no implementation.

Consider adding logic or documentation to detail how deposit_to_forge, check_balance_on_forge, and estimate_fee should operate. This helps consumers understand the intended usage.


7-10: Basic test module declared.

At present, the test module is empty. Add unit tests for these new public functions to ensure correctness once they are implemented.

execution/contracts/package.json (1)

2-8: Updated Dependencies Versions Verification

The dependency versions for @openzeppelin/contracts, @openzeppelin/contracts-upgradeable, @story-protocol/protocol-core, and @story-protocol/protocol-periphery have been bumped. Please ensure that these new versions are fully compatible with our contract implementations and that no breaking changes have been introduced by these updates.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dea7353 and 7952205.

⛔ Files ignored due to path filters (2)
  • execution/Cargo.lock is excluded by !**/*.lock
  • execution/contracts/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • .env.example (1 hunks)
  • execution/contracts/package.json (1 hunks)
  • execution/contracts/src/ForgeRegistry.sol (5 hunks)
  • execution/contracts/src/ForgeStorage.sol (1 hunks)
  • execution/crates/payment/Cargo.toml (1 hunks)
  • execution/crates/payment/src/lib.rs (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .env.example
  • execution/crates/payment/Cargo.toml
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (10)
execution/contracts/src/ForgeRegistry.sol (7)

24-24: Solid usage of ReentrancyGuardUpgradeable.

Protecting your contract from re-entrancy attacks in payment and withdrawal operations is prudent.


97-102: Ensure correct initialisation with _batcherWallet.

Including _batcherWallet in the constructor ensures correct usage of the onlyBatcher modifier. Double-check that your deployment script passes the correct wallet address during initialisation.


219-229: Licensing terms integration appears cohesive.

Registering the licence terms and attaching them to the IP is logically consistent with your current architecture. Ensure any future updates to PILicenseTemplate or ILicensingModule remain backward compatible.


255-260: The receive() function is straightforward.

Funds are credited to the sender’s balance, with the unlockBlockTime reset. This aligns well with your deposit approach.


262-271: Possible edge case for zero-balance users.

Calling unlock() with a zero balance reverts, which is logical. Confirm there are no scenarios where a user might need to set an unlock time prior to depositing funds.


273-279: Lock function with zero-balance revert.

Your logic prevents users from locking zero-balance accounts. While consistent, verify that no workflow requires a user to re-lock after fully withdrawing.


301-312: View functions are neatly structured.

Accessors for balances, nonces, and unlock block times are clear and consistent with the userData mapping.

execution/contracts/src/ForgeStorage.sol (2)

5-9: UserInfo struct covers essential fields.

Storing balance, unlockBlockTime, and nonce caters to fundamental user fund management. Ensure future additions do not break storage layout.


11-15: Public mapping and batcherWallet variable are clearly defined.

batcherWallet for the onlyBatcher checks and the userData mapping for user funds tracking are both straightforward. The __GAP array is a sound approach for preserving storage space.

execution/contracts/package.json (1)

9-12: DevDependencies Validation

The devDependencies remain unaltered, which is acceptable as there was no need for version changes here. However, please verify that the existing versions of ds-test and forge-std continue to support our testing framework without any issues.

Comment on lines 230 to 242
uint256 gasUsed = startGas - gasleft();
uint256 refundAmount = gasUsed * tx.gasprice;

if (userData[submitter].balance < refundAmount) {
revert SubmissionInsufficientBalance(
submitter,
userData[submitter].balance,
refundAmount
);
}

userData[submitter].nonce++;
userData[submitter].balance -= refundAmount;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential risk of insufficient contract balance for refund.

The refund logic calculates the gas used and transfers the refundAmount to the batcher. Consider verifying the contract’s Ether balance before calling .transfer(), to prevent unintended reverts if the contract’s balance is insufficient, even if userData[submitter].balance covers the cost.

Comment on lines +252 to +253
payable(msg.sender).transfer(refundAmount);
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider verifying contract balance before transferring.

If the contract’s Ether balance is below refundAmount, this call will revert. Checking address(this).balance >= refundAmount can provide a clearer error message.


🏁 Script executed:

#!/bin/bash
rg '\.transfer\(' -A 3

Length of output: 558


Review: Add Balance Verification Before Fund Transfers

The refund transfer operation at
execution/contracts/src/ForgeRegistry.sol, lines 252‑253, currently executes

    payable(msg.sender).transfer(refundAmount);

without checking if the contract holds enough Ether to cover refundAmount. This can lead to an unexpected revert if the balance is insufficient. I recommend adding a balance check such as:

require(address(this).balance >= refundAmount, "Insufficient funds for refund");

This approach not only prevents unintended transaction failures but also provides a clearer error message. Please consider applying a similar balance verification to other transfer operations in the contract if applicable.

Copy link

@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 (7)
execution/contracts/src/ForgeRegistry.sol (7)

2-2: Consider using a more flexible pragma version.

The current pragma ^0.8.26 is very specific. Consider using a more flexible version range like ^0.8.0 to ease future upgrades while maintaining compatibility with OpenZeppelin contracts.

-pragma solidity ^0.8.26;
+pragma solidity ^0.8.0;

27-27: Consider making UNLOCK_BLOCK_TIME configurable.

The unlock time is hardcoded to 1 hour. Consider making it configurable by the contract owner to allow for adjustments based on business needs.

-    uint256 public constant UNLOCK_BLOCK_TIME = 3600 seconds;
+    uint256 public UNLOCK_BLOCK_TIME;

45-49: Add NatSpec documentation for the Terms struct.

The Terms struct lacks documentation explaining the purpose of each field. Consider adding NatSpec comments to improve code maintainability.

+    /// @notice Struct defining the terms of an IP license
+    /// @param transferable Whether the license can be transferred
+    /// @param commercial Whether commercial use is allowed
+    /// @param commercialAttribution Whether attribution is required for commercial use
     struct Terms {
         bool transferable;
         bool commercial;
         bool commercialAttribution;
     }

52-63: Consider adding more indexed parameters to events.

The PaymentReceived and FundsWithdrawn events could benefit from indexing the amount parameter to allow efficient filtering of high-value transactions.

-    event PaymentReceived(address indexed sender, uint256 amount);
+    event PaymentReceived(address indexed sender, uint256 indexed amount);
-    event FundsWithdrawn(address indexed recipient, uint256 amount);
+    event FundsWithdrawn(address indexed recipient, uint256 indexed amount);

93-135: Consider emitting an event after initialization.

The initialize function performs critical setup but doesn't emit an event. Consider adding an event to log the initialization parameters for better transparency and auditability.

+    event ForgeRegistryInitialized(
+        address indexed ipAssetRegistry,
+        address indexed registrationWorkflows,
+        address indexed batcherWallet
+    );

     function initialize(
         // ... parameters ...
     ) public initializer {
         // ... existing code ...
+        emit ForgeRegistryInitialized(
+            ipAssetRegistryAddress,
+            registrationWorkflowsAddress,
+            _batcherWallet
+        );
     }

229-229: Consider making the gas refund multiplier configurable.

The gas refund multiplier is hardcoded to 110%. Consider making it configurable by the contract owner to adjust for varying network conditions.

+    uint256 public gasRefundMultiplier = 110;
     // ... in register function ...
-    uint256 refundAmount = (gasUsed * tx.gasprice * 110) / 100;
+    uint256 refundAmount = (gasUsed * tx.gasprice * gasRefundMultiplier) / 100;

259-263: Consider adding a minimum deposit requirement.

The receive function accepts any amount. Consider adding a minimum deposit requirement to prevent dust transactions that could lead to higher gas costs relative to the deposit amount.

+    uint256 public minDeposit = 0.01 ether;
     receive() external payable nonReentrant {
+        require(msg.value >= minDeposit, "Deposit amount too low");
         userData[msg.sender].balance += msg.value;
         userData[msg.sender].unlockBlockTime = 0;
         emit PaymentReceived(msg.sender, msg.value);
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7952205 and d9df4bb.

📒 Files selected for processing (1)
  • execution/contracts/src/ForgeRegistry.sol (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (2)
execution/contracts/src/ForgeRegistry.sol (2)

80-85: LGTM! Well-implemented modifier with custom error.

The onlyBatcher modifier effectively restricts access and provides clear error messages.


304-314: LGTM! Well-implemented view functions.

The view functions provide clear access to user data without any state modifications.

Copy link

@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 (4)
execution/contracts/src/ForgeRegistry.sol (4)

19-28: Constant naming consistency.
Although UNLOCK_BLOCK_TIME clearly states its purpose, you might consider adding further context in a comment to clarify that it equates to one hour, given its value of 3600 seconds. This can aid readability.


45-50: Unused struct detected.
The Terms struct currently has no usage in the contract. If you plan to incorporate customisable terms in a future iteration, consider adding a TODO note referencing the relevant ticket or roadmap item. Otherwise, it may be removed to minimise confusion.


66-68: Remove or implement NoSubmitter error.
The NoSubmitter error is declared but never used in the contract. If you plan to throw this error under specific conditions, please implement it; otherwise, removal is recommended to keep the codebase clean.


183-257: Refund calculation and transfer considerations.

  1. The partial refund logic calculates (gasUsed * tx.gasprice * 110) / 100. While this approach is valid, it is approximate and can be influenced by any gas overhead before measuring startGas. Documenting the 110% premium or making it adjustable might help manage future fee changes.
  2. Using .transfer() enforces a 2300-gas stipend. This is typically safer but can fail if msg.sender is a contract with a complex fallback. If you anticipate calls from contracts that require more gas in fallback, consider using .call with nonReentrant.
  3. The checks for both contract balance and userData[submitter].balance look correct, preventing unintended reverts and freeload transactions.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9df4bb and b4e012a.

📒 Files selected for processing (2)
  • execution/contracts/src/ForgeRegistry.sol (5 hunks)
  • execution/crates/payment/src/lib.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • execution/crates/payment/src/lib.rs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (4)
execution/contracts/src/ForgeRegistry.sol (4)

7-17: Imports look well-structured and cohesive.
No issues found regarding the addition of ReentrancyGuardUpgradeable and new Story Protocol imports. These imports seem necessary and appropriate for the new licensing and payment logic.


259-264: Safe deposit mechanism.
Using a receive() function with nonReentrant effectively prevents re-entrancy attacks when users send Ether. The immediate assignment to userData[msg.sender].balance appears logically sound. Consider logging zero-value deposits if they are pertinent to your business logic.


266-283: Lock/unlock workflow is straightforward.
The approach to set unlockBlockTime on unlock() and reset it to 0 on lock() is intuitively clear. If users call unlock() repeatedly, they repeatedly push back the unlock time. Ensure this is the desired behaviour for your user experience.


285-302: Withdrawal flow is aligned with user balance checks.

  1. Verifying amount against senderData.balance and ensuring the unlockBlockTime has passed are strong controls.
  2. Resetting unlockBlockTime to 0 post-withdrawal encourages a fresh lock period before the next withdrawal.
  3. Generally well-structured logic for fund release in an upgradable 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.

1 participant