Skip to content

Conversation

@fbac
Copy link
Collaborator

@fbac fbac commented Mar 3, 2025

Context around Merkle Trees in #563
Closes #499

The following is the expected sequence of events:

  • A node generates and submits a PayerReport.
  • All the other nodes call attestPayerReport if they can confirm its validity.
  • Nodes in the network listen for attestations and tracks them. Upon reaching majority, the confirmPayerReport can be called.
  • When a PayerReport is confirmed, any node can submit batches to settleUsageBatch. The PayerReport contract is expected to track batches submissions to prevent duplicates.
  • settleUsageBatch verifies the provided payers and amounts leafs are included in the PayerReport Merkle tree. If verified, the Payer.settleUsage is called with the list of payers and amounts to settle the usage.

Nodes attest to PayerReports, and once majority has been reached confirmPayerReport can be called for settlement.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Enhanced the usage settlement process to handle batches more efficiently with improved verification.
    • Introduced a new reporting interface enabling users to submit, attest, and confirm usage data reports.
    • Added events for tracking report submissions, attestations, confirmations, and settlement statuses.
    • Updated terminology for contracts related to distribution to better reflect current functionality.
  • Bug Fixes
    • Clarified documentation for events to accurately represent their context and usage.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request modifies the IPayer interface by updating the UsageSettled event, removing the BatchUsageSettled event, and replacing the settleUsageBatch function with a new settleUsage function that accommodates batch processing with an aggregated Merkle proof. Additionally, a new interface IPayerReport is introduced, which includes events and functions for managing usage reports, such as submitting, attesting, and confirming reports.

Changes

File(s) Change Summary
contracts/src/interfaces/IPayer.sol - Updated UsageSettled event to use originatorNode
- Removed BatchUsageSettled event
- Replaced settleUsageBatch with settleUsage(address originatorNode, uint256 reportIndex, address[] calldata payers, uint256[] calldata amounts)
- Renamed RewardsContractUpdated to DistributionContractUpdated and updated related functions
contracts/src/interfaces/IPayerReport.sol - Added new interface IPayerReport
- Defined struct PayerReport
- Added events: PayerReportSubmitted, PayerReportAttested, PayerReportConfirmed, PayerReportPartiallySettled, PayerReportFullySettled
- Added functions: submitPayerReport, attestPayerReport, listPayerReports, getPayerReport, settleUsageBatch, setMaxBatchSize, getMaxBatchSize

Sequence Diagram(s)

sequenceDiagram
    participant Originator
    participant IPayer
    Originator->>IPayer: settleUsage(originatorNode, reportIndex, payers, amounts)
    IPayer-->>Originator: Validate Merkle proof and process settlement
Loading
sequenceDiagram
    participant Originator
    participant Validator
    participant IPayerReport
    Originator->>IPayerReport: submitPayerReport(PayerReport)
    IPayerReport-->>Originator: Emit PayerReportSubmitted event
    Validator->>IPayerReport: attestPayerReport(originatorNode, reportIndex)
    IPayerReport-->>Validator: Emit PayerReportAttested event
    Originator/Other->>IPayerReport: getPayerReport(originatorNode, reportIndex)
    IPayerReport-->>Originator: Return PayerReport details
    Originator/Other->>IPayerReport: settleUsageBatch(originatorNode, reportIndex, offset, payers, amounts, proof)
    IPayerReport-->>Originator: Emit PayerReportPartiallySettled event
Loading

Possibly related PRs

  • feat: Payer interface #558: Involves modifications to the usage settlement functions (settleUsage and settleUsageBatch) in the IPayer interface with changes similar to those in this PR.

Suggested reviewers

  • neekolas

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 96c8393 and ee5f365.

📒 Files selected for processing (1)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)

🪧 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.
  • @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
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 (4)
contracts/src/interfaces/IPayer.sol (1)

278-285: Validate ranges and offset in settleUsage.

While this interface accurately represents the new settlement approach, pay special attention in the implementation to avoid out-of-bounds usage of offset + payers.length, especially if partial usage slices are processed. Confirm that any leftover usage in the report remains valid or is settled in subsequent calls.

contracts/src/interfaces/IPayerReport.sol (3)

60-84: Double-check parameter coverage and validation in submitPayerReport.

All required data for usage tracking is presented (sequence IDs, timestamps, Merkle root, etc.). In the implementation, validate:

  1. Array length matching for payers and amountsSpent.
  2. A sensible maximum on payers.length to avoid potential block gas-limit issues.

94-104: Consider partial or malicious attestations in confirmPayerReport.

Majority attestation is critical. Confirm that the final checks account for any malicious or repeated attestations so that only unique node attestations count. Document how “majority” is defined (e.g., number of active node operators).


106-113: Review pagination needs in listPayerReports.

Currently, this returns all usage reports for the node in a single call. If the list grows large, you might consider a paginated approach to prevent potential out-of-gas issues on-chain.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8362d and 86d83dd.

📒 Files selected for processing (2)
  • contracts/src/interfaces/IPayer.sol (1 hunks)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Solidity
contracts/src/interfaces/IPayerReport.sol

[warning] 2-2: Version constraint ^0.8.0 contains known severe issues. Refer to the documentation for details.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build pre-baked anvil-xmtpd
🔇 Additional comments (5)
contracts/src/interfaces/IPayer.sol (1)

264-277: Ensure Merkle-proof parameters and docstrings remain consistent in implementation.

The docstring nicely explains the purpose of offset, payers, amounts, and proof. However, be sure that any implementation enforces array-length checks, offset bounds, and Merkle proof validity. Consider clarifying in the docstring that the ArrayLengthMismatch error will be used if payers.length != amounts.length.

contracts/src/interfaces/IPayerReport.sol (4)

24-38: Confirm array length consistency for event PayerReportSubmitted.

This event publishes arrays payers and amountsSpent, but the interface omits explicit mention of their expected matching lengths. Ensure the implementation logs consistent arrays to avoid potential indexing or data mismatch.


40-55: Events PayerReportAttested and PayerReportConfirmed look solid.

They succinctly capture essential details, including the Merkle root. Just confirm in implementation that you consistently index by reportIndex where necessary, to avoid confusion with only storing the reportMerkleRoot.


85-92: Attestation logic might need access-control checks.

While attestPayerReport is open to “nodes,” ensure the implementation verifies that only legitimate/active node operators can attest. Otherwise, the system may allow fraudulent attestations.


114-141: Ensure storage integrity for getPayerReport.

The return values cover all essential fields. When implementing, carefully map indexes to stored arrays and confirm that the attestation count and isConfirmed states cannot be manipulated without a proper majority attestation process.

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 (5)
contracts/src/interfaces/IPayerReport.sol (5)

28-38: Consider indexing the reportMerkleRoot field for easier log filtering.

Indexing reportMerkleRoot in the PayerReportSubmitted event can improve discoverability of relevant logs by Merkle root value.

 event PayerReportSubmitted(
     address indexed originatorNode,
     uint256 indexed reportIndex,
     uint256 startingSequenceID,
     uint256 endingSequenceID,
     uint256 lastMessageTimestamp,
     uint256 reportTimestamp,
-    bytes32 reportMerkleRoot,
+    bytes32 indexed reportMerkleRoot,
     address[] payers,
     uint256[] amountsSpent
 );

43-46: Include the report index in the PayerReportAttested event.

Capturing the explicit reportIndex in the event makes it easier to trace back a particular attestation to a specific usage report.

 event PayerReportAttested(
     address indexed originatorNode,
-    bytes32 reportMerkleRoot
+    uint256 indexed reportIndex,
+    bytes32 indexed reportMerkleRoot
 );

51-54: Include the report index in the PayerReportConfirmed event.

This helps downstream services or off-chain indexers easily correlate confirmations with the correct report index, especially if multiple reports share the same Merkle root.

 event PayerReportConfirmed(
     address indexed originatorNode,
-    bytes32 reportMerkleRoot
+    uint256 indexed reportIndex,
+    bytes32 indexed reportMerkleRoot
 );

74-83: Consider using a struct to reduce the number of parameters.

A struct-based parameter approach can improve readability, maintainability, and help avoid "stack too deep" issues in implementations.

-function submitPayerReport(
-    address originatorNode,
-    uint256 startingSequenceID,
-    uint256 endingSequenceID,
-    uint256 lastMessageTimestamp,
-    uint256 reportTimestamp,
-    bytes32 reportMerkleRoot,
-    address[] calldata payers,
-    uint256[] calldata amountsSpent
-) external;
+
+struct UsageReport {
+    address originatorNode;
+    uint256 startingSequenceID;
+    uint256 endingSequenceID;
+    uint256 lastMessageTimestamp;
+    uint256 reportTimestamp;
+    bytes32 reportMerkleRoot;
+    address[] payers;
+    uint256[] amountsSpent;
+}
+
+function submitPayerReport(UsageReport calldata report) external;

107-113: Clarify the documentation to reflect multiple returned values.

The docstring describes a single “first sequence ID,” whereas the function returns an array. For accuracy, rename or clarify the returned arrays in the Solidity doc comments.

 /**
  * @notice Returns a list of all payer reports for a given originator node.
- * @return startingSequenceID The first sequence ID in the report.
- * @return reportsMerkleRoot The Merkle root for the detailed usage data.
+ * @return startingSequenceIDs The array of starting sequence IDs for each report.
+ * @return reportsMerkleRoots The array of Merkle roots for each report.
  */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 86d83dd and fca3705.

📒 Files selected for processing (1)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build pre-baked anvil-xmtpd
🔇 Additional comments (1)
contracts/src/interfaces/IPayerReport.sol (1)

2-2:

Details

✅ Verification successful

Check the validity of Solidity version.

While 0.8.28 may be acceptable if it's officially released, it's prudent to verify its stability and ensure support in your compiler toolchain.


🌐 Web query:

Is "pragma solidity 0.8.28" an official release from the Solc stable versions?

💡 Result:

Yes, Solidity v0.8.28 is an official stable release of the Solidity compiler. The release was announced by the Solidity team on October 9, 2024, through multiple official channels including GitHub[1][6], the Solidity blog[6], and developer forums[10]. It includes new features like full support for transient storage state variables of value types (a precursor to complete transient storage functionality)[1][10], compiler optimizations to reduce memory usage[1][6], and bug fixes[1][4].

Key indicators of its official status:

Developers can safely use pragma solidity 0.8.28; in contracts, though the latest version (0.8.29 as of March 2025) should generally be preferred for security updates[3][7]. The release follows Semantic Versioning rules, with 0.8.x versions maintaining backward compatibility[3][6].

Citations:


Solidity Version Validated

  • Verified that pragma solidity 0.8.28; references an officially released and stable compiler version (released October 9, 2024).
  • While 0.8.28 is supported and valid for use, note that version 0.8.29 is now available as of March 2025 for additional enhancements and security updates.

@fbac fbac marked this pull request as ready for review March 4, 2025 18:32
@fbac fbac requested a review from a team as a code owner March 4, 2025 18:32
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: 2

🧹 Nitpick comments (7)
contracts/src/interfaces/IPayer.sol (1)

379-382: Document return values more thoroughly.

The function’s doc comment is clear but does not specify how the returned contract value might be used. Consider adding a brief note indicating that downstream contracts or scripts may rely on this address for distribution logic.

contracts/src/interfaces/IPayerReport.sol (6)

28-44: Event emission for full usage details.

Emitting full data via PayerReportSubmitted is valuable for off-chain processing. Double-check that large arrays do not exceed gas limits on mainnet.


46-54: Event clarifies node attestations but watch for spam.

PayerReportAttested is straightforward. However, if many nodes re-attest frequently, this can bloat logs. Consider implementing measures (e.g., minimum stake or checks) to discourage unnecessary attestations.


78-85: Ensure reentrancy protections while submitting reports.

submitPayerReport should be guarded by best practices in the implementation to avoid reentrancy across other calls. A simple nonReentrant or checks-effects-interactions pattern can help.


87-95: Attestation logic.

attestPayerReport is flexible, but ensure code addresses stale or duplicate attestations. Possibly store a mapping from (originatorNode, reportIndex, attestor) to track repeated attempts.


96-106: Confirm majority threshold.

confirmPayerReport depends on a “majority attestation.” Clarify or document how many attestations are needed. This detail, while not in the interface, is crucial for consistent usage in implementations.


108-115: Pagination concerns.

listPayerReports returns all stored report roots for the node. For large sets, consider a block-based or offset-based approach in the future to avoid hitting view function call size limits.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 614dace and 1bd78d0.

📒 Files selected for processing (2)
  • contracts/src/interfaces/IPayer.sol (5 hunks)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build pre-baked anvil-xmtpd
🔇 Additional comments (12)
contracts/src/interfaces/IPayer.sol (5)

71-71: Confirm event usage alignment with implementation.

Renaming the parameter to originatorNode clarifies the event’s meaning. Verify that any references to the old nodeId are updated throughout the codebase to avoid inconsistencies.


73-77: Ensure references to fees destination are updated throughout the documentation.

Renaming references from “rewards contract” to “distribution contract” is coherent, but any remaining references or documentation must also be adjusted to maintain consistency.


98-99: Check for orphaned references to NotRewardsContract.

Introducing NotDistributionContract is correct given the shift to a distribution contract. Ensure that all checks preventing calls from the old rewards contract are replaced with the new error as well.


264-279: Validate batch settlement logic parameters.

The new settleUsage method signature adds clarity by indicating an offset for a contiguous subset of data. Confirm that the contract enforcing the offset logic fully validates array bounds, preventing out-of-range errors.


362-367: Confirm distribution contract address correctness.

The setter function and docs now reference the distribution contract. Ensure that security checks are in place so only authorized addresses can update this contract.

contracts/src/interfaces/IPayerReport.sol (7)

1-2: Solidity version looks current.

Using pragma solidity 0.8.28; addresses prior warnings about outdated 0.8.0 usage. This should mitigate known vulnerabilities or compiler bugs documented for earlier 0.8.x releases.


4-7: Interface documentation is concise and clear.

The introduction covers the purpose of handling usage reports and batch settlements. This clarity aids implementers in understanding the interface’s responsibilities.


13-22: Struct definition is well-structured.

The UsageReport fields provide essential metadata and the merkle root for verification. Ensure implementers handle data length checks (e.g., payers vs. amountsSpent arrays) to avoid mismatches or out-of-bounds errors.


55-63: Confirmation workflow is direct.

PayerReportConfirmed allows finalizing a majority-attested report. Ensure that finalization logic in the implementation re-checks the data’s validity in case a new malicious attestation appears after submission.


64-73: UsageSettled event usage.

Emitting a UsageSettled event in this interface indicates successful settlement steps. Align the event’s parameters with final settlement data so external services can track what’s been consumed from the merkle tree.


116-126: Spot-check array sizes.

getPayerReport conveys the entire UsageReport. Implementations should verify that arrays payers and amountsSpent remain within practical limits for storage or event emission.


157-162: Getter aligns usage boundaries.

getMaxBatchSize straightforwardly provides an external limit. Ensure internal logic references it consistently to avoid out-of-bounds or overflows.

* Emits `BatchUsageSettled` and multiple `UsageSettled` events.
*/
function settleUsageBatch(
address originatorNode,
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this will also need to include a Batch Merkle Proof, won't it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually I think offset is not needed in Payer.settleUsage function.
The way I see it is the PayerReport.settleUsageBatch accepts the proofs and verifies them. Only when the []payers and []amounts are verified as part of the merkle tree we call Payer.settleUsage([]payer, []amount), which is a dumb function just to settle what we agreed on.

Copy link
Contributor

@neekolas neekolas Mar 5, 2025

Choose a reason for hiding this comment

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

Ahhh. I see. Makes sense

@neekolas
Copy link
Contributor

neekolas commented Mar 4, 2025

@fbac

Upon reaching majority, the confirmPayerReport can be called.

Could we do this automatically as the attestations come in. Otherwise I'm not sure who would be responsible for calling this

event UsageSettled(
address indexed originatorNode,
uint256 indexed reportIndex,
uint256 offset,
Copy link
Contributor

Choose a reason for hiding this comment

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

For this event to be indexable by the nodes I believe we would need to have the payers and the amounts

Copy link
Contributor

@neekolas neekolas Mar 4, 2025

Choose a reason for hiding this comment

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

Otherwise the node would have to do a bunch of work to reconstruct the tree and figure out what was being settled.

It's particularly tricky if the report that was confirmed and settled wasn't one the node agreed on. From the perspective of indexing settled usage, I think you'd still want to process the update even if you were in the minority and didn't attest to the report.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree, modifying this part too.

Also, with the latest commit I added a uint16 batches to the PayerReport struct, which should be calculated off-chain based on getMaxBatchSize(). Other nodes can reconstruct that data and agree on it.

I think this is interesting because we don't submit the amount of payers and amounts anymore, so I don't see a reliable way of calculating the amount of batches expected for a single report, tracking what was already settled, etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense to me. Do we want it to be the number of batches, or just the number of leaves in the tree? I'm fine with either, but the number of leaves lets the caller adjust the batch size as needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I like the number to be leaves in the tree. It reduces ambiguity and hidden knowledge (such as batches has to be N payers max)

@fbac
Copy link
Collaborator Author

fbac commented Mar 5, 2025

@fbac

Upon reaching majority, the confirmPayerReport can be called.

Could we do this automatically as the attestations come in. Otherwise I'm not sure who would be responsible for calling this

@nick I was concerned about having a clear separation of concerns in the contract ABI, so attestPayerReport doesn't return 2 types of events depending the amount of confirmations, and Nodes would attest to a PayerReport while counting the confirmations off-chain, then any node could call confirmPayerReport.

But yes, it's definitely possible to combine the logic into attestPayerReport.

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 (6)
contracts/src/interfaces/IPayer.sol (2)

264-271: Clarify prerequisite in documentation

The doc states “Assumes that the PayerReport contract has already verified…” Consider adding a brief note describing what happens if the caller fails to meet this prerequisite, or if the caller is not the PayerReport contract. This helps clarify security assumptions for third parties reading the interface’s docs.


281-281: Minor doc alignment

Ensure the phrasing “to the distribution contract” is consistent with the rest of the file. If usage or examples exist elsewhere, re-check for consistency (e.g., “transfer of pending fees”).

contracts/src/interfaces/IPayerReport.sol (4)

1-3: Pragma and license

pragma solidity 0.8.28; is sufficiently recent. If your build pipeline flags known issues, consider bumping to a newer 0.8.x version.


62-72: Event: PayerReportPartiallySettled

The doc references “Emits a UsageSettled event” in line 134, but the actual event name is PayerReportPartiallySettled. For consistency, update the doc to reference the correct event name.

- * Emits a UsageSettled event.
+ * Emits a PayerReportPartiallySettled event.

102-109: Function: listPayerReports

Returning only startingSequenceIDs and reportsMerkleRoots might be limiting. Consider also returning a status (e.g., attested, confirmed, etc.) to reduce repeated calls.

function listPayerReports(address originatorNode)
  external
  view
- returns (uint256[] memory startingSequenceIDs, bytes32[] memory reportsMerkleRoots);
+ returns (
+     uint256[] memory startingSequenceIDs,
+     bytes32[] memory reportsMerkleRoots,
+     bool[] memory isConfirmed
+ );

145-150: Function: setMaxBatchSize

If you plan to impose batch size limits, you might also need to track them in the actual settlement logic. Let me know if you’d like a suggested patch verifying offset + payers.length <= maxBatchSize.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1bd78d0 and e5ec448.

📒 Files selected for processing (2)
  • contracts/src/interfaces/IPayer.sol (5 hunks)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build pre-baked anvil-xmtpd
🔇 Additional comments (19)
contracts/src/interfaces/IPayer.sol (9)

71-71: Good rename to originatorNode for clarity

Switching from nodeId to originatorNode more clearly conveys the purpose of this event parameter.


73-73: Event name is concise

No issues spotted. The event name and parameter are straightforward.


76-76: Consistent naming for distribution contract

Renaming to DistributionContractUpdated aligns event naming across the codebase.


98-99: Error type changes

Renaming to NotDistributionContract is consistent with the new terminology for the distribution contract.


273-276: Parameter additions

Adding originatorNode and reportIndex to the settleUsage function ensures that usage batches are properly tied to a specific node’s report.


287-292: Improved clarity for fees transfer

The updated docstring and method name transferFeesToDistribution are aligned, making the usage of this function more intuitive.


360-365: Set distribution contract logic

The doc references a single setter function for the distribution contract. Ensure at the implementation level that only authorized roles (e.g., contract owner) may call this method to avoid malicious updates.
Would you like a shell script to confirm usage of an access control check in the implementation?


376-379: Getter naming clarity

getDistributionContract() read function name is consistent with setDistributionContract().


383-385: Nodes contract retrieval [approve]

Renaming and clarifying doc ensures consistent naming. Looks good.

contracts/src/interfaces/IPayerReport.sol (10)

5-7: Interface documentation

High-level notice accurately describes the handling of usage reports and batch settlements.


9-22: PayerReport struct

Including batches and reportMerkleRoot is essential for partial settlement logic. Please ensure external code validates that batches is correctly computed to align with off-chain usage.
Would you like a script to search for batches usage in the codebase to check for correct calculations?


27-42: Event: PayerReportSubmitted

Sufficiently descriptive event captures the necessary details for off-chain indexing of the usage report.


44-51: Event: PayerReportAttested

Captures attestations in a straightforward manner.
No issues found.


53-60: Event: PayerReportConfirmed

Clear intention for final report confirmation.
No concerns here.


74-78: Event: PayerReportFullySettled

Event name and parameters convey full settlement status clearly.


84-91: Function: submitPayerReport

Ensure that off-chain or other watchers can reconstruct the full usage data from the emitted event. The doc references only partial data stored on chain. If an index or authority is required, confirm references or pointers are included.
Would you like a script to review where submitPayerReport is called and confirm presence of indexing for off-chain watchers?


93-100: Function: attestPayerReport

Method signature is concise. Encouraging nodes to provide attestations fosters trustless validation.


110-120: Function: getPayerReport

Reading the entire PayerReport struct from a single call is convenient for on-chain introspection.


151-155: Function: getMaxBatchSize

A read-only function for batch size checks is a useful complement.

@fbac fbac force-pushed the 03_03-interface-payerreport branch from e5ec448 to 96c8393 Compare March 5, 2025 11:01
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 (1)
contracts/src/interfaces/IPayer.sol (1)

385-385: Improved return value documentation

The return value documentation now clearly indicates the return type as nodesContract, improving clarity.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e5ec448 and 96c8393.

📒 Files selected for processing (2)
  • contracts/src/interfaces/IPayer.sol (5 hunks)
  • contracts/src/interfaces/IPayerReport.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • contracts/src/interfaces/IPayerReport.sol
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build pre-baked anvil-xmtpd
🔇 Additional comments (8)
contracts/src/interfaces/IPayer.sol (8)

71-71: The UsageSettled event has been updated with an originatorNode parameter

The event structure has been changed to include the originatorNode as an indexed parameter, which allows for more efficient filtering by the node that originated the usage settlement. This aligns with the new flow where reports are generated by specific nodes and verified by others.


73-77: Terminology changed from "rewards" to "distribution" for better clarity

The documentation and naming have been updated to use "distribution contract" instead of "rewards contract," which likely better represents the contract's role in distributing fees rather than simply rewarding nodes.


99-99: Error renamed for consistency with new terminology

The error has been renamed from NotRewardsContract to NotDistributionContract to maintain consistency with the terminology changes throughout the interface.


292-292: Function renamed for consistency with new terminology

The function has been renamed from transferFeesToRewards to transferFeesToDistribution to maintain consistency with the terminology changes throughout the interface.


365-365: Function renamed for consistency with new terminology

The function has been renamed from setRewardsContract to setDistributionContract to maintain consistency with the terminology changes throughout the interface.


379-379: Function renamed for consistency with new terminology

The function has been renamed from getRewardsContract to getDistributionContract to maintain consistency with the terminology changes throughout the interface.


273-273: Parameter added for Merkle proof verification

Referencing the previous discussion around the need for a Batch Merkle Proof, I see you've redesigned the system to handle this concern. The originatorNode and reportIndex parameters now serve to reference a specific report that has already had its Merkle proof verified, addressing the concern raised earlier about proof verification.


263-277:

Details

❓ Verification inconclusive

New settlement flow using PayerReport and Merkle proofs

The settleUsage function has been significantly modified to work with the new PayerReport interface. It now:

  1. Takes an originatorNode parameter to track which node submitted the report
  2. Includes a reportIndex parameter to reference the specific report
  3. Assumes the Merkle proof verification has already been performed by the PayerReport contract

The design separates concerns appropriately, with proof verification happening in PayerReport and actual settlement in Payer.


🏁 Script executed:

#!/bin/bash
# Check if there's an IPayerReport interface implementation that handles the Merkle proof verification
# Expected: a file with IPayerReport interface defining functions for submitting and verifying reports

echo "Searching for PayerReport interface definition..."
fd -e sol | xargs grep -l "interface IPayerReport"

echo "Searching for Merkle proof verification in the codebase..."
rg -A 5 -B 5 "verify.*[Mm]erkle" --type sol

Length of output: 404


Below is a revised review comment that reflects the latest context. Note that the IPayerReport interface is present, confirming the intended separation of concerns. However, since our automated search for Merkle proof verification code required a modified search and further manual verification is advised, please double-check that the actual Merkle proof verification is implemented as expected in the PayerReport.

Settlement Flow Update – Verify Merkle Proof Delegation

The modifications to the settleUsage function in contracts/src/interfaces/IPayer.sol correctly reflect the new settlement flow. In this setup:

  • The addition of the originatorNode parameter tracks which node submitted the report.
  • The inclusion of the reportIndex parameter clearly references a specific report.
  • The design assumes that the Merkle proof has already been verified in the PayerReport contract.

Next Steps:

  • Verify: Confirm that the IPayerReport interface (located at contracts/src/interfaces/IPayerReport.sol) implements Merkle proof verification as intended.
  • Manual check: Ensure that the delegated Merkle proof verification logic is correctly wired with the new settlement flow.

@neekolas
Copy link
Contributor

neekolas commented Mar 5, 2025

@nick I was concerned about having a clear separation of concerns in the contract ABI, so attestPayerReport doesn't return 2 types of events depending the amount of confirmations, and Nodes would attest to a PayerReport while counting the confirmations off-chain, then any node could call confirmPayerReport.

That's probably fine. We'll just need to think through how we ensure that all Payer Reports that can be confirmed do get confirmed. If the node doing the attesting doesn't confirm it, we need some way to remind someone else to do the work or an automation to find dangling reports.

@fbac fbac merged commit cc87104 into main Mar 7, 2025
10 of 11 checks passed
@fbac fbac deleted the 03_03-interface-payerreport branch March 7, 2025 11:56
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.

PayerReport contract interface

3 participants