Skip to content

Comments

Fix reentrancy vulnerability#128

Merged
Utilitycoder merged 3 commits intoFundable-Protocol:mainfrom
wheval:fix/reentrancy
Jul 28, 2025
Merged

Fix reentrancy vulnerability#128
Utilitycoder merged 3 commits intoFundable-Protocol:mainfrom
wheval:fix/reentrancy

Conversation

@wheval
Copy link
Contributor

@wheval wheval commented Jul 25, 2025

Closes #127

ren

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive coding rules document for Cairo projects, outlining best practices and workflow recommendations.
    • Added systematic reentrancy protection to payment streaming functions, enhancing contract security against reentrancy attacks.
  • Tests

    • Added extensive tests simulating malicious reentrancy attacks to verify the effectiveness of reentrancy protection in payment streaming operations.
    • Included tests confirming normal contract operations remain unaffected.

@coderabbitai
Copy link

coderabbitai bot commented Jul 25, 2025

Walkthrough

A reentrancy guard is integrated into the PaymentStream contract, systematically wrapping all externally accessible, state-mutating functions to prevent reentrancy attacks. The contract's logic is refactored to follow the Checks-Effects-Interactions (CEI) pattern. Comprehensive malicious contract-based tests are introduced to verify the effectiveness of the reentrancy protection, and a new coding rules document for Cairo projects is added.

Changes

Cohort / File(s) Change Summary
PaymentStream Contract: Reentrancy Protection
src/payment_stream.cairo
Integrated ReentrancyGuardComponent and applied reentrancy guard start/end calls to all externally accessible, state-mutating functions (withdraw, withdraw_max, cancel, transfer_stream, collect_protocol_fee). Refactored logic to avoid nested guards and follow the CEI pattern. Split protocol fee collection into guarded and internal unguarded methods.
Reentrancy Attack & Protection Tests
tests/test_reentrancy_protection.cairo
Added contracts simulating malicious ERC20 tokens and attackers targeting withdraw, cancel, and transfer_stream for reentrancy. Implemented tests for direct and cross-function reentrancy attacks, ensuring all protected functions revert on attack. Included tests for normal operations and withdraw_max. Helper functions and cheat codes are used for setup and context manipulation.
Cairo Coding Rules Documentation
.cursor/rules/cairo-coder.mdc
Introduced a new documentation file outlining coding standards, project structure, workflow, naming conventions, testing strategies, and guidelines for using the Cairo Coder MCP tool.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PaymentStream
    participant ReentrancyGuard
    participant ERC20Token

    User->>PaymentStream: withdraw/withdraw_max/cancel/transfer_stream/collect_protocol_fee
    PaymentStream->>ReentrancyGuard: start_guard()
    alt Guard not active
        PaymentStream->>PaymentStream: update state (Checks, Effects)
        PaymentStream->>ERC20Token: external call (Interactions)
        PaymentStream->>ReentrancyGuard: end_guard()
        PaymentStream-->>User: return result
    else Guard active
        PaymentStream-->>User: revert with reentrancy error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
Integrate ReentrancyGuard component into PaymentStream contract (#127)
Apply reentrancy protection to all vulnerable functions: withdraw, withdraw_max, cancel, transfer_stream, collect_protocol_fee (#127)
Refactor logic to follow CEI pattern: state updates before external calls (#127)
Add comprehensive reentrancy attack tests (direct, cross-function, read-only) (#127)
Provide gas impact analysis (#127) No code or documentation related to gas analysis observed in the changes.

Assessment against linked issues: Out-of-scope changes

Code Change (file_path) Explanation
Addition of Cairo coding rules documentation (.cursor/rules/cairo-coder.mdc) This documentation file is not related to reentrancy protection or the PaymentStream contract.

Poem

In Cairo's code, a guard now stands,
To shield our streams from sneaky hands.
Attackers tried, but all were caught—
Reentrancy: foiled, their schemes for naught!
With rules well penned and tests anew,
The bunny hops—secure, it's true!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @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.

@Utilitycoder
Copy link
Contributor

Thanks for the good work, @wheval. When do you think the PR will be ready?

@wheval wheval marked this pull request as ready for review July 28, 2025 12:50
@wheval
Copy link
Contributor Author

wheval commented Jul 28, 2025

Thanks for the good work, @wheval. When do you think the PR will be ready?

The PR is ready, sorry for the delay!

Copy link
Contributor

@Utilitycoder Utilitycoder left a comment

Choose a reason for hiding this comment

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

Good job. Thanks for taking time to work on the issue.

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 (1)
tests/test_reentrancy_protection.cairo (1)

186-339: Consider if separate attacker contracts are necessary

The MaliciousWithdrawAttacker, MaliciousCancelAttacker, and MaliciousTransferAttacker contracts appear redundant since the MaliciousERC20 already implements these attack vectors. Consider removing these unless they're intended for testing direct attacks vs token-transfer-triggered attacks.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b65ff3d and 5aaddde.

📒 Files selected for processing (3)
  • .cursor/rules/cairo-coder.mdc (1 hunks)
  • src/payment_stream.cairo (12 hunks)
  • tests/test_reentrancy_protection.cairo (1 hunks)
⏰ 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: tests
🔇 Additional comments (9)
.cursor/rules/cairo-coder.mdc (1)

69-126: Well-structured development workflow guidelines

The development workflow section provides excellent guidance on coding standards, testing practices, and effective use of the Cairo Coder MCP tool. The emphasis on atomic queries and providing specific context aligns with best practices for AI-assisted development.

src/payment_stream.cairo (5)

8-8: ReentrancyGuard component properly integrated

The ReentrancyGuard component from OpenZeppelin is correctly integrated with all necessary elements: import, component declaration, internal implementation, storage substorage, and event handling.

Also applies to: 36-38, 49-49, 69-70, 102-102


404-419: Correct refactoring of fee collection to avoid nested guards

The separation of collect_protocol_fee (with guard) and _collect_protocol_fee_internal (without guard) properly prevents nested reentrancy guards when called from other protected functions like _withdraw.

Also applies to: 732-732


817-834: Withdraw functions properly protected with CEI pattern

Both withdraw and withdraw_max are correctly wrapped with reentrancy guards. The internal _withdraw function follows the Checks-Effects-Interactions pattern by updating all state (lines 711-726) before making external calls (lines 732-733).


836-870: transfer_stream correctly implements reentrancy protection

The function is properly wrapped with reentrancy guards and follows the CEI pattern. All state updates and the NFT transfer occur within the protected section.


972-1101: Cancel function properly implements reentrancy protection with CEI pattern

The function correctly wraps all operations with reentrancy guards and meticulously follows the CEI pattern:

  • All state updates (lines 1025-1059) including status change, balance updates, and NFT burn
  • External calls (lines 1071-1072, 1088) only after state is finalized

This is the most complex function and it's implemented securely.

tests/test_reentrancy_protection.cairo (3)

31-184: Well-designed malicious ERC20 for reentrancy testing

The MaliciousERC20 contract effectively simulates reentrancy attacks with:

  • Multiple attack modes for different PaymentStream functions
  • Attack count limitation to prevent infinite loops
  • Realistic attack trigger during token transfers

This provides comprehensive test coverage for the reentrancy guards.


425-561: Comprehensive reentrancy attack test coverage

The test cases effectively verify reentrancy protection for all critical functions:

  • Proper setup with malicious tokens configured for each attack type
  • Realistic scenarios with time progression for withdrawals
  • Correct assertion of reentrancy guard errors

These tests confirm the reentrancy protection is working as intended.


606-662: Good coverage of normal operations post-protection

This test effectively verifies that the reentrancy protection doesn't interfere with normal operations. It tests withdraw, transfer_stream, and cancel functions with non-malicious tokens, ensuring the guards only activate during actual attacks.

@Utilitycoder Utilitycoder merged commit f15de56 into Fundable-Protocol:main Jul 28, 2025
3 checks passed
@wheval
Copy link
Contributor Author

wheval commented Jul 28, 2025

Hello ser @Utilitycoder, I just noticed that I accidentally committed a Cursor MCP config file in this PR. While I used Cursor to assist during development, I wrote and reviewed the logic myself — the tool was more of a support than a driver.

I’m going to clean that up and also fix a test that isn’t passing properly. I’ll open a follow-up PR shortly to address both.

Just wanted to flag this in case the config file gave the wrong impression. Appreciate your understanding!

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.

Fix Reentrancy Vulnerabilities in Payment Stream Contract

2 participants