Skip to content

feat(contract): enforce min_score_to_earn gate in record_payment#191

Open
leocagli wants to merge 1 commit into
Stellar-Ecosystem:mainfrom
leocagli:feat/min-score-to-earn-enforcement
Open

feat(contract): enforce min_score_to_earn gate in record_payment#191
leocagli wants to merge 1 commit into
Stellar-Ecosystem:mainfrom
leocagli:feat/min-score-to-earn-enforcement

Conversation

@leocagli

Copy link
Copy Markdown
Contributor

Fixes #140

Problem

SpendingPolicy.min_score_to_earn was stored on-chain, displayed in SpendingPolicy.tsx as "Min Score to Earn", and settable via update_policy — but never enforced. Agents below the threshold gained SCORE_SUCCESS from every successful payment at the same rate as qualified agents, making the field purely cosmetic.

Chosen Semantic

Agents below min_score_to_earn do not gain SCORE_SUCCESS from successful payments. Payment stats (total_payments, successful_payments, total_volume_stroops) are still recorded so credit history remains accurate. Score accumulation resumes as soon as the agent reaches the threshold (through other means or operator adjustment).

This is the "earn-gate" interpretation: existing agents can still use services; they just cannot improve their score until they qualify. (The alternative — blocking spending entirely — would be a breaking change to check_spending_allowed.)

Changes

contract/agents/src/lib.rs

New helpers:

fn is_new_day(now: u64, last_reset_ledger: u64) -> bool { ... }

fn apply_score_success(current: i32, min_score_to_earn: i32) -> i32 {
    if current >= min_score_to_earn {
        (current + SCORE_SUCCESS).min(MAX_SCORE)
    } else {
        current   // below threshold — no score increment
    }
}

record_payment: moved SpendingPolicy load to before the score update so min_score_to_earn can be read without a second storage hit. Score now goes through apply_score_success(agent.score, min_score).

Doc comment added to min_score_to_earn field explaining the semantic.

#[cfg(test)] module with 8 tests:

  • 6 for apply_score_success (no gate, below gate, at gate, above gate, near-cap, at-max)
  • 2 boundary tests for is_new_day

🤖 Generated with Claude Code

Closes Stellar-Ecosystem#140

SpendingPolicy.min_score_to_earn was stored and displayed in the UI but
never checked — agents below the threshold earned score at the same rate as
qualified agents, making the field cosmetic.

Semantic: 'agents below min_score_to_earn do not gain SCORE_SUCCESS from
successful payments; payment stats (total_payments, successful_payments,
volume) are still recorded so credit history remains accurate.'

Changes:
- Added apply_score_success(current, min_score_to_earn) helper that
  encapsulates the gate logic: returns current score unchanged when below
  the threshold, or (current + SCORE_SUCCESS).min(MAX_SCORE) when at or above
- Moved SpendingPolicy load to before the score update in record_payment so
  the gate can be applied without a second storage read
- Added is_new_day helper (replaces the inline DAY_LEDGERS check reused from
  the policy section) for clarity and reuse
- Added doc comment on SpendingPolicy.min_score_to_earn explaining the semantic
- Added #[cfg(test)] module with 8 tests: 6 for apply_score_success
  (no gate, below gate, at gate, above gate, cap, at-max) and 2 boundary
  tests for is_new_day
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@leocagli, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 3 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2927a551-42c4-4f5c-86d0-122d9183ad70

📥 Commits

Reviewing files that changed from the base of the PR and between 6fb6da9 and cf5e974.

📒 Files selected for processing (1)
  • contract/agents/src/lib.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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.

MIN_SCORE enforcement in SpendingPolicy (min_score_to_earn) is stored but never enforced anywhere in either the contract or the backend

1 participant