Skip to content

Conversation

jo-elimu
Copy link
Member

@jo-elimu jo-elimu commented Aug 30, 2025

Resolves #86

Summary by CodeRabbit

  • New Features

    • Added the ability to remove a rejected distribution from the front of the distribution queue and an event emitted when a queue pair is processed.
  • Bug Fixes

    • Processing now requires distributions to be approved; non-approved items are blocked from processing.
  • Tests

    • Added test verifying rejected distributions are removed and queue length updates accordingly; updated related assertion message.
  • Chores

    • Updated gas-report metrics to include the new flow and bumped backend package version to 0.6.0.

@jo-elimu jo-elimu requested a review from a team as a code owner August 30, 2025 08:50
Copy link

netlify bot commented Aug 30, 2025

Deploy Preview for web3-sponsors canceled.

Name Link
🔨 Latest commit 5a145a9
🔍 Latest deploy log https://app.netlify.com/projects/web3-sponsors/deploys/68b2be957b11fc0008468391

Copy link

coderabbitai bot commented Aug 30, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds QueueHandler.removeRejectedDistribution to dequeue the front distribution when DistributionVerifier marks it rejected; processQueuePair now only accepts approved distributions. Tests and gas report updated to exercise and report the new removal path. (49 words)

Changes

Cohort / File(s) Summary
Smart contract: QueueHandler
backend/contracts/QueueHandler.sol
Added removeRejectedDistribution() public function: checks queue non-empty, reads front distribution number, requires distributionVerifier.isDistributionRejected(...) true, and dequeues the front item. Removed DistributionRejectedError() and simplified processQueuePair() to require approved distributions and emit QueuePairProcessed(Distribution, Sponsorship).
Tests: QueueHandler
backend/test/QueueHandler.ts
Added “Remove Rejected Distribution” test that enqueues a distribution, marks it rejected via verifier, calls removeRejectedDistribution(), and asserts queue length goes from 1 to 0. Updated assertion message in “Process Queue Pair” test to reflect new restriction.
Gas report & metadata
backend/hardhat-gas-report.md, backend/package.json
Updated gas report to include removeRejectedDistribution metrics and adjusted QueueHandler/SponsorshipQueue/DistributionQueue figures; bumped backend/package.json version from 0.5.0 to 0.6.0.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant QH as QueueHandler
  participant DQ as DistributionQueue
  participant DV as DistributionVerifier

  Caller->>QH: removeRejectedDistribution()
  QH->>DQ: getLength()
  alt length == 0
    QH-->>Caller: revert (empty queue)
  else length > 0
    QH->>DQ: queueNumberFront()
    QH->>DV: isDistributionRejected(frontNumber)
    alt rejected == true
      QH->>DQ: dequeue()
      QH-->>Caller: return (success)
    else rejected == false
      QH-->>Caller: revert ("Only approved distributions can be processed" / not rejected)
    end
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Assessment against linked issues

Objective Addressed Explanation
Remove rejected distributions from the queue (#86)

Out-of-scope changes

Code Change Explanation
Bumped package version backend/package.json (version change) Version bump is release metadata and not required by issue #86.
Gas report updates backend/hardhat-gas-report.md (added metrics for removeRejectedDistribution and adjusted figures) Gas-report and metric adjustments are ancillary artifacts and not part of the functional objective in #86.

Possibly related PRs

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 45e5d5d and 5a145a9.

📒 Files selected for processing (2)
  • backend/contracts/QueueHandler.sol (3 hunks)
  • backend/hardhat-gas-report.md (5 hunks)
✨ 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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: 0

🧹 Nitpick comments (4)
backend/contracts/QueueHandler.sol (3)

83-95: Consider access control: gate removal to DAO operators or document permissionless intent

Right now anyone can call this and mutate queue state. If the policy is that only DAO operators should manage queue hygiene (like processQueuePair), add a roles check; otherwise add a NatSpec note that this is intentionally permissionless. Keeping the queue clean supports timely disbursements aligned with elimu.ai's mission: "elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months."

Apply if you prefer gating:

-    function removeRejectedDistribution() public {
+    function removeRejectedDistribution() external {
+        require(roles.isDaoOperator(msg.sender), "Only DAO operators can remove rejected distributions");

89-95: Emit an event when a rejected distribution is dequeued

Adds traceability for off-chain indexers and ops dashboards.

Apply:

-        // Remove the distribution from the queue
-        distributionQueue.dequeue();
+        // Remove the distribution from the queue
+        emit RejectedDistributionRemoved(distributionQueueNumber);
+        distributionQueue.dequeue();

Add alongside existing events (near Lines 17–20):

event RejectedDistributionRemoved(uint24 distributionQueueNumber);

85-92: Prefer custom errors over string requires for gas and consistency

You already use DistributionRejectedError; mirror that pattern here.

Apply:

-        require(distributionQueue.getLength() > 0, "The distribution queue cannot be empty");
+        if (distributionQueue.getLength() == 0) revert DistributionQueueEmpty();
@@
-        require(isDistributionRejected, "Only rejected distributions can be removed from the queue");
+        if (!isDistributionRejected) revert DistributionNotRejected();

Add error declarations near Line 21:

error DistributionQueueEmpty();
error DistributionNotRejected();
backend/test/QueueHandler.ts (1)

147-162: Add negative-path tests to lock behavior

  • Empty queue → revert with "The distribution queue cannot be empty".
  • Front not rejected (unverified or approved) → revert with the current message.
  • If you add DAO-operator gating as suggested, include a test that non-operators are reverted.

You can extend this block with:

await expect(queueHandler.removeRejectedDistribution())
  .to.be.rejectedWith("The distribution queue cannot be empty");

await distributionQueue.addDistribution("HIN", "abc");
await expect(queueHandler.removeRejectedDistribution())
  .to.be.rejectedWith("Only rejected distributions can be removed from the queue");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fcf5b28 and 9844ea4.

📒 Files selected for processing (3)
  • backend/contracts/QueueHandler.sol (1 hunks)
  • backend/hardhat-gas-report.md (5 hunks)
  • backend/test/QueueHandler.ts (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). (3)
  • GitHub Check: build (windows-latest, 20.x)
  • GitHub Check: build (windows-latest, 18.x)
  • GitHub Check: build (ubuntu-latest, 18.x)
🔇 Additional comments (3)
backend/test/QueueHandler.ts (1)

147-162: Good positive-path test for removal

The test clearly proves a rejected front item is removed. Setup is minimal and reuses the fixture well.

backend/hardhat-gas-report.md (2)

44-45: Gas report includes new method entry — looks right

New removeRejectedDistribution line present; keep this synced with test coverage going forward.


12-12: Verify report regeneration came from a clean run

Numbers for add/verify/update and deployments shifted. Please confirm this file was regenerated from the same commit (e.g., HARDHAT_NETWORK=hardhat npm test -- --report-gas) to avoid drift across environments.

Also applies to: 26-26, 58-61, 78-81

coderabbitai[bot]
coderabbitai bot previously approved these changes Aug 30, 2025
@nya-elimu nya-elimu merged commit 69b1a27 into elimu-ai:main Aug 30, 2025
12 checks passed
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: 1

🧹 Nitpick comments (3)
backend/hardhat-gas-report.md (1)

42-45: Gas for new removal path looks healthy; add CI threshold to guard regressions

processQueuePair ~105.9k and removeRejectedDistribution ~54.5k align with expectations. Consider adding per-function gas ceilings in CI to prevent drift. This supports reliable payouts at scale, in line with elimu.ai's mission: elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

backend/contracts/QueueHandler.sol (2)

54-59: Approval-only processing: good; consider small gas/read ordering

LGTM enforcing approval before processing. Optional: check sponsorshipQueue.getLength() before the verifier call to save an external read when sponsorships are empty. Also consider custom errors to shave gas.


72-74: Emit an event for successful pairing

Add an event for observability/auditing.

Apply this diff:

-        // Emit event
-        // TODO
+        // Emit event
+        emit QueuePairProcessed(distributionQueueNumber);

And declare the event (outside this hunk):

event QueuePairProcessed(uint24 distributionQueueNumber);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9844ea4 and 45e5d5d.

⛔ Files ignored due to path filters (1)
  • backend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • backend/contracts/QueueHandler.sol (2 hunks)
  • backend/hardhat-gas-report.md (5 hunks)
  • backend/package.json (1 hunks)
  • backend/test/QueueHandler.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • backend/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/test/QueueHandler.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). (3)
  • GitHub Check: build (windows-latest, 18.x)
  • GitHub Check: build (windows-latest, 20.x)
  • GitHub Check: build (ubuntu-latest, 18.x)
🔇 Additional comments (2)
backend/hardhat-gas-report.md (2)

26-26: Slight verifier cost uptick; confirm root cause

verifyDistribution avg rose (~63,421). Likely due to new status path usage—please confirm via test trace to ensure no unintended storage touches.


78-81: Deployments gas bump: still within budget?

QueueHandler avg ~971k and SponsorshipQueue ~1.106M are <4% of block limit. Validate against your deployment budget matrix and historical baselines.

Comment on lines 76 to 88
/// @notice Remove rejected distribution from the distribution queue
function removeRejectedDistribution() public {
// Verify that the queue of distributions is not empty
require(distributionQueue.getLength() > 0, "The distribution queue cannot be empty");

// Verify that the next distribution in the queue has been rejected
uint24 distributionQueueNumber = distributionQueue.queueNumberFront();
bool isDistributionRejected = distributionVerifier.isDistributionRejected(distributionQueueNumber);
require(isDistributionRejected, "Only rejected distributions can be removed from the queue");

// Remove the distribution from the queue
distributionQueue.dequeue();
}
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

removeRejectedDistribution: clarify permissions + emit event

If permissionless cleanup is intended, great—document it. If not, gate with roles. Emit an event and prefer external visibility.

Apply this diff:

-    function removeRejectedDistribution() public {
+    function removeRejectedDistribution() external {
-        // Verify that the queue of distributions is not empty
+        // Verify that the queue of distributions is not empty
         require(distributionQueue.getLength() > 0, "The distribution queue cannot be empty");
 
-        // Verify that the next distribution in the queue has been rejected
+        // Verify that the next distribution in the queue has been rejected
         uint24 distributionQueueNumber = distributionQueue.queueNumberFront();
         bool isDistributionRejected = distributionVerifier.isDistributionRejected(distributionQueueNumber);
         require(isDistributionRejected, "Only rejected distributions can be removed from the queue");
 
-        // Remove the distribution from the queue
+        // Remove the distribution from the queue
         distributionQueue.dequeue();
+        emit RejectedDistributionRemoved(distributionQueueNumber);
     }

And either add role gating:

-    function removeRejectedDistribution() external {
+    function removeRejectedDistribution() external {
+        require(roles.isDaoOperator(msg.sender), "Only DAO operators can remove rejected distributions");

Declare the event (outside this hunk):

event RejectedDistributionRemoved(uint24 distributionQueueNumber);

🏁 Script executed:

#!/bin/bash
set -e

# Locate the QueueHandler.sol file
file=$(find . -type f -name QueueHandler.sol | head -n1)
echo "File path: $file"

echo "==== Top of file (1-200) ===="
sed -n '1,200p' "$file"

echo "==== Events in file ===="
grep -R "event " -n "$file"

echo "==== Function definitions ===="
grep -R "function " -n "$file"

Length of output: 4927


Clarify removeRejectedDistribution permissions and emit event

  • Change visibility from public to external.
  • Either document permissionless design or restrict callers via
    require(roles.isDaoOperator(msg.sender), "Only DAO operators can remove rejected distributions");
  • Emit an event after dequeue and declare it:
-    function removeRejectedDistribution() public {
+    function removeRejectedDistribution() external {
+        require(roles.isDaoOperator(msg.sender), "Only DAO operators can remove rejected distributions");
         // Verify that the queue of distributions is not empty
         require(distributionQueue.getLength() > 0, "The distribution queue cannot be empty");

         // Verify that the next distribution in the queue has been rejected
         uint24 distributionQueueNumber = distributionQueue.queueNumberFront();
         bool isDistributionRejected = distributionVerifier.isDistributionRejected(distributionQueueNumber);
         require(isDistributionRejected, "Only rejected distributions can be removed from the queue");

         // Remove the distribution from the queue
         distributionQueue.dequeue();
+        emit RejectedDistributionRemoved(distributionQueueNumber);
     }

Declare the event (outside contract functions):

event RejectedDistributionRemoved(uint24 distributionQueueNumber);

elimu.ai’s mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

🤖 Prompt for AI Agents
In backend/contracts/QueueHandler.sol around lines 76 to 88, change
removeRejectedDistribution visibility from public to external, decide and
enforce caller permissions (either document as permissionless or add a require
like require(roles.isDaoOperator(msg.sender), "Only DAO operators can remove
rejected distributions");), and after distributionQueue.dequeue() emit an event
indicating which distribution was removed; also declare the event outside
functions as event RejectedDistributionRemoved(uint24 distributionQueueNumber);
so the emitted event uses the distributionQueueNumber variable captured before
dequeue.

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.

backend: Remove rejected distributions from the queue
2 participants