Skip to content

Refined rev-share-limit variable names#1874

Open
Goader wants to merge 6 commits intomainfrom
task/refine-rev-share-limit-variable-names
Open

Refined rev-share-limit variable names#1874
Goader wants to merge 6 commits intomainfrom
task/refine-rev-share-limit-variable-names

Conversation

@Goader
Copy link
Copy Markdown
Contributor

@Goader Goader commented Apr 6, 2026

Refined rev-share-limit variable names

closes: #1786

Summary


Why

  • New variable names better represent their meaning

Testing

  • Automatic, CI testing
  • Manual validation

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

@Goader Goader self-assigned this Apr 6, 2026
@Goader Goader requested a review from a team as a code owner April 6, 2026 10:20
Copilot AI review requested due to automatic review settings April 6, 2026 10:20
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Apr 7, 2026 3:01pm
ensnode.io Ready Ready Preview, Comment Apr 7, 2026 3:01pm
ensrainbow.io Ready Ready Preview, Comment Apr 7, 2026 3:01pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 6, 2026

🦋 Changeset detected

Latest commit: 5b08c84

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 24 packages
Name Type
@namehash/ens-referrals Major
ensapi Major
ensindexer Major
ensadmin Major
ensrainbow Major
fallback-ensapi Major
enssdk Major
enscli Major
enskit Major
ensskills Major
@ensnode/datasources Major
@ensnode/ensrainbow-sdk Major
@ensnode/ensdb-sdk Major
@ensnode/ensnode-react Major
@ensnode/ensnode-sdk Major
@ensnode/ponder-sdk Major
@ensnode/ponder-subgraph Major
@ensnode/shared-configs Major
@docs/ensnode Major
@docs/ensrainbow Major
@docs/mintlify Major
@namehash/namehash-ui Major
@ensnode/enskit-react-example Patch
@ensnode/integration-test-env Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Rename and reshape rev-share-limit and pie-split API fields: replace reward-pool keys (totalAwardPoolValueawardPool), rename rev-share fields (minQualifiedRevenueContributionminBaseRevenueContribution, qualifiedRevenueSharemaxBaseRevenueShare), rename metric fields (standardAwardValueuncappedAwardValue, awardPoolApproxValuecappedAwardValue), and add per-edition baseAnnualRevenueContribution (remove global constant).

Changes

Cohort / File(s) Summary
Release doc
.changeset/bright-foxes-dance.md
Added changeset documenting the field renames and minor release.
Docs / Examples
packages/ens-referrals/README.md
Updated README examples and console output to use renamed fields (minBaseRevenueContribution, maxBaseRevenueShare, uncappedAwardValue, cappedAwardValue).
Rev-share schemas & validation
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts
Replaced/added schema fields (awardPool, minBaseRevenueContribution, baseAnnualRevenueContribution, maxBaseRevenueShare) and updated refinements/messages (including maxBaseRevenueShare <= 1 and capped/uncapped invariants).
Rev-share serialized types
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialized-types.ts
Renamed serialized interface properties: totalAwardPoolValueawardPool, minQualifiedRevenueContributionminBaseRevenueContribution, added baseAnnualRevenueContribution, and standardAwardValue/awardPoolApproxValueuncappedAwardValue/cappedAwardValue.
Rev-share serialization logic
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialize.ts
Emit renamed serialized fields (awardPool, minBaseRevenueContribution, baseAnnualRevenueContribution, maxBaseRevenueShare, uncappedAwardValue, cappedAwardValue) using existing price serialization.
Rev-share rules & core API
packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts
Updated ReferralProgramRulesRevShareLimit shape and buildReferralProgramRulesRevShareLimit signature to accept awardPool, minBaseRevenueContribution, baseAnnualRevenueContribution, maxBaseRevenueShare; removed BASE_REVENUE_CONTRIBUTION_PER_YEAR.
Rev-share metrics & leaderboard
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts, .../leaderboard.ts
Renamed metric fields and function signatures to accept/produce uncappedAwardValue/cappedAwardValue, pass rules into metrics builders/validators, use maxBaseRevenueShare for scaling, and track pool via rules.awardPool.
Pie-split schemas & types
packages/ens-referrals/src/v1/award-models/pie-split/...
Renamed rule property and serialized output from totalAwardPoolValueawardPool; updated schema, serialized-types, serializer, and metric invariants to use awardPool.
Edition defaults
packages/ens-referrals/src/v1/edition-defaults.ts
Added per-edition baseAnnualRevenueContribution argument in the 2026-03 edition construction.
Mocks & app fixtures
apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/mocks-v1.ts
Updated mock leaderboards to use rules.awardPool instead of rules.totalAwardPoolValue.
Tests
packages/ens-referrals/src/v1/api/zod-schemas.test.ts, .../rev-share-limit/leaderboard.test.ts, packages/ens-referrals/src/v1/leaderboard-page.test.ts
Updated fixtures, helpers, assertions and expected values to reflect renamed fields and revised ranking/qualification behavior.

Sequence Diagram(s)

(silently omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • namehash/ensnode#1663: Renames several RevShareLimit fields; directly touches the same rev-share-limit modules.
  • namehash/ensnode#1780: Overlaps on referrals award-models (schemas, serialization, metrics, leaderboard) and may conflict.
  • namehash/ensnode#1562: Prior changes to v1 referrals models; modifies related files and fixtures.

Suggested labels

ensanalytics

Poem

🐰 I hopped through fields with a careful nibble,
Swapped names so the meaning wouldn't dribble.
"Base", "max", "uncapped", "capped" in a line,
Tests, docs, and schemas aligned just fine.
A tiny hop for clarity — carrot time! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refined rev-share-limit variable names' directly and clearly describes the main focus of the changeset: renaming variables in the rev-share-limit reward model to improve naming clarity.
Description check ✅ Passed The description follows the template with all required sections: Summary, Why, Testing, and Pre-Review Checklist. It clearly references the related issue (#1786) and explains the purpose of the changes.
Linked Issues check ✅ Passed The PR fully addresses all coding requirements from issue #1786: it renames minQualifiedRevenueContribution→minBaseRevenueContribution, qualifiedRevenueShare→maxBaseRevenueShare, standardAwardValue→uncappedAwardValue, awardPoolApproxValue→cappedAwardValue, and additionally renames totalAwardPoolValue→awardPool and moves BASE_REVENUE_CONTRIBUTION_PER_YEAR into baseAnnualRevenueContribution, all with complete implementation across tests, schemas, and serialization.
Out of Scope Changes check ✅ Passed All changes are directly related to the variable renaming objectives specified in issue #1786. Updates across test fixtures, schemas, serialization, and documentation are all necessary to implement the requested renames consistently throughout the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task/refine-rev-share-limit-variable-names

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

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 6, 2026

Greptile Summary

This PR is a pure rename/refactoring across the rev-share-limit award model, replacing four field names with clearer equivalents: minQualifiedRevenueContributionminBaseRevenueContribution, qualifiedRevenueSharemaxBaseRevenueShare, standardAwardValueuncappedAwardValue, and awardPoolApproxValuecappedAwardValue. The changes are applied consistently across TypeScript interfaces, Zod schemas, serializers, serialized types, tests, and README documentation.

  • All 10 changed files are updated coherently — no stale references to old names remain in logic or type definitions
  • Internal race-algorithm state variables (e.g., qualifiedAwardValueAmount) are correctly left unchanged as they are private implementation details, not part of the public API
  • The changeset version bump is marked minor; since the package is at v1.9.0 and these are breaking public API field renames (serialized API responses, exported TypeScript types, and README examples all change), a major bump would be more appropriate under strict semver

Confidence Score: 5/5

Safe to merge — all renames are applied consistently with no stale references or logic changes.

All 10 changed files are internally consistent with the new field names. No logic was altered — only identifier names. The sole open question is the semver bump level, which is a P2 style concern that does not block merge.

Only .changeset/bright-foxes-dance.md warrants a second look regarding whether minor is the correct bump level for a post-1.0.0 package with public API field renames.

Important Files Changed

Filename Overview
.changeset/bright-foxes-dance.md Changeset marks renaming of public API fields as 'minor' rather than 'major' for a post-1.0.0 package
packages/ens-referrals/README.md Documentation updated to reflect all four new field names consistently
packages/ens-referrals/src/v1/api/zod-schemas.test.ts Test data and type annotations updated to use minBaseRevenueContribution and maxBaseRevenueShare
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialize.ts Serialization functions correctly reference the renamed fields throughout
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialized-types.ts Serialized TypeScript interfaces updated to use uncappedAwardValue and cappedAwardValue
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts Zod validation schemas updated to reference minBaseRevenueContribution and maxBaseRevenueShare
packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.test.ts All test assertions migrated from awardPoolApproxValue/standardAwardValue to cappedAwardValue/uncappedAwardValue
packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts Leaderboard builder uses maxBaseRevenueShare; internal race-state variable qualifiedAwardValueAmount left unchanged
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts Metrics interfaces and builders fully updated; uncappedAwardValue and cappedAwardValue replace old names
packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts Rules interface and validator correctly use minBaseRevenueContribution and maxBaseRevenueShare

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ReferralEvent input] --> B[buildReferrerLeaderboardRevShareLimit]
    B --> C{isReferrerQualifiedRevShareLimit}
    C -->|threshold check| D[rules.minBaseRevenueContribution]
    C -->|renamed from minQualifiedRevenueContribution| D
    B --> E[scalePrice]
    E -->|share fraction| F[rules.maxBaseRevenueShare]
    F -->|renamed from qualifiedRevenueShare| F
    B --> G[buildAwardedReferrerMetricsRevShareLimit]
    G --> H[uncappedAwardValue\nmaxBaseRevenueShare × totalBaseRevenueContribution\nrenamed from standardAwardValue]
    G --> I[cappedAwardValue\npool-capped actual award\nrenamed from awardPoolApproxValue]
    G --> J[ReferrerLeaderboardRevShareLimit output]
    J --> K[rules: minBaseRevenueContribution\nrules: maxBaseRevenueShare]
    J --> L[referrers: uncappedAwardValue\nreferrers: cappedAwardValue]
Loading

Reviews (1): Last reviewed commit: "renamed variables" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Renames rev-share-limit rule/metric field names across the v1 referrals API to better reflect meaning (per #1786).

Changes:

  • Renamed RevShareLimit rule fields: minQualifiedRevenueContributionminBaseRevenueContribution, qualifiedRevenueSharemaxBaseRevenueShare.
  • Renamed RevShareLimit awarded metric fields: standardAwardValueuncappedAwardValue, awardPoolApproxValuecappedAwardValue.
  • Updated validation, serialization/Zod schemas, tests, and README examples to use the new names.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts Renames rule fields and updates validation/qualification logic to match.
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts Renames awarded metric fields and updates invariants/validation/builders.
packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts Updates award computation to use renamed rule/metric fields.
packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.test.ts Updates RevShareLimit leaderboard tests for renamed fields.
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts Updates RevShareLimit Zod schemas and refinements for renamed fields.
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialized-types.ts Updates serialized type names for renamed fields.
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialize.ts Updates RevShareLimit serializers to emit renamed fields.
packages/ens-referrals/src/v1/api/zod-schemas.test.ts Updates v1 API schema tests to use renamed RevShareLimit fields.
packages/ens-referrals/README.md Updates public docs/examples to the renamed fields.
.changeset/bright-foxes-dance.md Declares a release bump for the API field renames.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts (1)

72-77: ⚠️ Potential issue | 🟡 Minor

Replace the stale awardPoolShare term in this invariant.

That name is no longer exposed by this type or the rest of the renamed API, so the doc now points readers at the wrong concept.

Doc-only cleanup
-   * Identifies if the referrer meets the qualifications of the {`@link` ReferralProgramRulesRevShareLimit} to receive a non-zero `awardPoolShare`.
+   * Identifies if the referrer meets the qualifications of the {`@link` ReferralProgramRulesRevShareLimit} to receive a non-zero award.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts` around
lines 72 - 77, Update the JSDoc invariant to use the current API term instead of
the stale `awardPoolShare` identifier; replace `awardPoolShare` with the renamed
property `awardShare` in the comment that describes the invariant for
ReferralProgramRulesRevShareLimit (the block referencing
`totalBaseRevenueContribution` and `isAdminDisqualified`) so the docs point at
the correct concept.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts`:
- Around line 126-137: The Zod schema must mirror
validateUnrankedReferrerMetricsRevShareLimit by rejecting any "unranked" record
whose uncappedAwardValue.amount or cappedAwardValue.amount is non-zero; update
the schema block that defines uncappedAwardValue, cappedAwardValue,
isAdminDisqualified, adminDisqualificationReason (the schema using valueLabel)
to add an additional .refine predicate that checks "if this record is unranked
(use the same unranked condition used in
validateUnrankedReferrerMetricsRevShareLimit) then uncappedAwardValue.amount ===
0 && cappedAwardValue.amount === 0", and return a clear message/path (e.g.,
path: ["uncappedAwardValue","cappedAwardValue"]) when violated so the serialized
API shape matches the runtime validator.

In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts`:
- Around line 188-210: The validator in metrics.ts enforces
cappedAwardValue.amount == 0n only for admin-disqualified referrers but misses
the contract that when metrics.isQualified === false (below-threshold)
cappedAwardValue must also be zero; update the validation logic after the
makePriceUsdcSchema parses to add a check for metrics.isQualified === false that
throws a descriptive Error if metrics.cappedAwardValue.amount !== 0n (similar to
the existing isAdminDisqualified check), referencing the same properties
(metrics.isQualified, metrics.cappedAwardValue.amount) and keeping the other
comparisons against rules.totalAwardPoolValue.amount and
metrics.uncappedAwardValue.amount intact.

---

Outside diff comments:
In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts`:
- Around line 72-77: Update the JSDoc invariant to use the current API term
instead of the stale `awardPoolShare` identifier; replace `awardPoolShare` with
the renamed property `awardShare` in the comment that describes the invariant
for ReferralProgramRulesRevShareLimit (the block referencing
`totalBaseRevenueContribution` and `isAdminDisqualified`) so the docs point at
the correct concept.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8b1dd26f-f231-448b-a5c1-88e14a85bd69

📥 Commits

Reviewing files that changed from the base of the PR and between d0c97a5 and f5b4ecc.

📒 Files selected for processing (10)
  • .changeset/bright-foxes-dance.md
  • packages/ens-referrals/README.md
  • packages/ens-referrals/src/v1/api/zod-schemas.test.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialize.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialized-types.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.test.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts

@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io April 6, 2026 15:49 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io April 6, 2026 15:49 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io April 6, 2026 15:49 Inactive
Copilot AI review requested due to automatic review settings April 6, 2026 16:19
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io April 6, 2026 16:19 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io April 6, 2026 16:19 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io April 6, 2026 16:19 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts`:
- Around line 139-145: The current .refine call incorrectly sets path to
["uncappedAwardValue","cappedAwardValue"] (which points to a nested path);
replace the .refine with .superRefine on the same Zod schema and, inside the
callback, check the same condition and call ctx.addIssue separately for each
offending sibling field (use paths ["uncappedAwardValue"] and
["cappedAwardValue"] respectively) with the appropriate message; use
ZodIssueCode.custom for the issues so each field gets its own validation error
instead of a nonexistent nested path.

In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts`:
- Around line 189-195: The current validator for
AwardedReferrerMetricsRevShareLimit.uncappedAwardValue only parses a PriceUsdc
but should enforce the documented invariant; compute expectedUncapped =
rules.maxBaseRevenueShare × metrics.totalBaseRevenueContribution inside the
validation logic (using the same numeric types/scale as makePriceUsdcSchema
expects) and either assert parsed uncappedAwardValue equals expectedUncapped or,
better, derive and set uncappedAwardValue from that computation instead of
trusting caller input; update
makePriceUsdcSchema("AwardedReferrerMetricsRevShareLimit.cappedAwardValue")
usage to still validate cappedAwardValue <= expectedUncapped and adjust
buildAwardedReferrerMetricsRevShareLimit() to derive uncappedAwardValue from
rules.maxBaseRevenueShare and metrics.totalBaseRevenueContribution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 46afcbc6-f698-4608-9a08-24db3381105a

📥 Commits

Reviewing files that changed from the base of the PR and between ae807a6 and 1443e64.

📒 Files selected for processing (2)
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts

@vercel vercel bot temporarily deployed to Preview – ensrainbow.io April 6, 2026 18:28 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io April 6, 2026 18:28 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io April 6, 2026 18:28 Inactive
Copy link
Copy Markdown
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts (1)

120-146: ⚠️ Potential issue | 🟠 Major

Mirror the rest of the unranked zero-metric contract in this schema.

validateUnrankedReferrerMetricsRevShareLimit() still rejects non-zero totalReferrals, totalIncrementalDuration, totalRevenueContribution.amount, and totalBaseRevenueContribution.amount, but this schema only encodes the zero-award checks. That leaves the serialized API shape looser than the runtime model and allows invalid unranked payloads to parse here.

Suggested schema tightening
     .object({
       referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
       totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
       totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
       totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`),
       totalBaseRevenueContribution: makePriceUsdcSchema(
         `${valueLabel}.totalBaseRevenueContribution`,
       ),
       rank: z.null(),
       isQualified: z.literal(false),
       uncappedAwardValue: makePriceUsdcSchema(`${valueLabel}.uncappedAwardValue`),
       cappedAwardValue: makePriceUsdcSchema(`${valueLabel}.cappedAwardValue`),
       isAdminDisqualified: z.boolean(),
       adminDisqualificationReason: z
         .string()
         .trim()
         .min(1, `${valueLabel}.adminDisqualificationReason must not be empty`)
         .nullable(),
     })
+    .refine((data) => data.totalReferrals === 0, {
+      message: `${valueLabel}.totalReferrals must be 0 for unranked referrers`,
+      path: ["totalReferrals"],
+    })
+    .refine((data) => data.totalIncrementalDuration === 0, {
+      message: `${valueLabel}.totalIncrementalDuration must be 0 for unranked referrers`,
+      path: ["totalIncrementalDuration"],
+    })
+    .refine((data) => data.totalRevenueContribution.amount === 0n, {
+      message: `${valueLabel}.totalRevenueContribution must be 0 for unranked referrers`,
+      path: ["totalRevenueContribution"],
+    })
+    .refine((data) => data.totalBaseRevenueContribution.amount === 0n, {
+      message: `${valueLabel}.totalBaseRevenueContribution must be 0 for unranked referrers`,
+      path: ["totalBaseRevenueContribution"],
+    })
     .refine((data) => data.uncappedAwardValue.amount === 0n, {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts`
around lines 120 - 146, The schema for unranked referrers currently only
enforces zero award values but must also mirror the runtime validator
validateUnrankedReferrerMetricsRevShareLimit: add checks to the zod object
(around the same chain where rank is z.null() and isQualified is
z.literal(false)) to require totalReferrals === 0, totalIncrementalDuration ===
0 (or duration.amount === 0 depending on the duration shape),
totalRevenueContribution.amount === 0n, and totalBaseRevenueContribution.amount
=== 0n; implement these as additional .refine() calls (or a single
.superRefine()) referencing the fields totalReferrals, totalIncrementalDuration,
totalRevenueContribution, and totalBaseRevenueContribution so the parsed API
shape matches the runtime validation.
♻️ Duplicate comments (1)
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts (1)

189-195: ⚠️ Potential issue | 🟠 Major

Don't accept an arbitrary uncappedAwardValue here.

This field is documented as rules.maxBaseRevenueShare × totalBaseRevenueContribution, but the validator only parses it as a generic PriceUsdc and the builder still takes it from callers. Any inflated uncappedAwardValue currently passes as long as cappedAwardValue <= uncappedAwardValue, which weakens the renamed contract. Recompute the expected uncapped amount from rules.maxBaseRevenueShare and totalBaseRevenueContribution here, or derive it inside buildAwardedReferrerMetricsRevShareLimit() instead of accepting it as input. Based on learnings: In packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts, AwardedReferrerMetricsRevShareLimit.standardAwardValue should not duplicate the generic PriceUsdc non-negative invariant; keep only the context-specific formula (“rules.qualifiedRevenueShare × totalBaseRevenueContribution”) and notes about pool independence.

Also applies to: 222-231

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts` around
lines 189 - 195, The code currently accepts an arbitrary uncappedAwardValue and
only validates it as a generic PriceUsdc; instead recompute and validate
uncappedAwardValue from the formula rules.maxBaseRevenueShare ×
totalBaseRevenueContribution (or move that derivation into
buildAwardedReferrerMetricsRevShareLimit()) and validate the computed value
against cappedAwardValue, rather than trusting caller input for
AwardedReferrerMetricsRevShareLimit.uncappedAwardValue; likewise remove the
redundant generic non-negative PriceUsdc check for
AwardedReferrerMetricsRevShareLimit.standardAwardValue and keep only the
context-specific invariant/description that it equals
rules.qualifiedRevenueShare × totalBaseRevenueContribution and is
pool-independent. Ensure references to makePriceUsdcSchema, cappedAwardValue,
standardAwardValue, buildAwardedReferrerMetricsRevShareLimit,
rules.maxBaseRevenueShare, rules.qualifiedRevenueShare, and
totalBaseRevenueContribution are used to locate and update the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts`:
- Around line 120-146: The schema for unranked referrers currently only enforces
zero award values but must also mirror the runtime validator
validateUnrankedReferrerMetricsRevShareLimit: add checks to the zod object
(around the same chain where rank is z.null() and isQualified is
z.literal(false)) to require totalReferrals === 0, totalIncrementalDuration ===
0 (or duration.amount === 0 depending on the duration shape),
totalRevenueContribution.amount === 0n, and totalBaseRevenueContribution.amount
=== 0n; implement these as additional .refine() calls (or a single
.superRefine()) referencing the fields totalReferrals, totalIncrementalDuration,
totalRevenueContribution, and totalBaseRevenueContribution so the parsed API
shape matches the runtime validation.

---

Duplicate comments:
In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts`:
- Around line 189-195: The code currently accepts an arbitrary
uncappedAwardValue and only validates it as a generic PriceUsdc; instead
recompute and validate uncappedAwardValue from the formula
rules.maxBaseRevenueShare × totalBaseRevenueContribution (or move that
derivation into buildAwardedReferrerMetricsRevShareLimit()) and validate the
computed value against cappedAwardValue, rather than trusting caller input for
AwardedReferrerMetricsRevShareLimit.uncappedAwardValue; likewise remove the
redundant generic non-negative PriceUsdc check for
AwardedReferrerMetricsRevShareLimit.standardAwardValue and keep only the
context-specific invariant/description that it equals
rules.qualifiedRevenueShare × totalBaseRevenueContribution and is
pool-independent. Ensure references to makePriceUsdcSchema, cappedAwardValue,
standardAwardValue, buildAwardedReferrerMetricsRevShareLimit,
rules.maxBaseRevenueShare, rules.qualifiedRevenueShare, and
totalBaseRevenueContribution are used to locate and update the logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0e0628e2-9060-4a54-a071-462eaecf1002

📥 Commits

Reviewing files that changed from the base of the PR and between 1443e64 and fb767c2.

📒 Files selected for processing (2)
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts

@Goader Goader requested a review from lightwalker-eth April 6, 2026 18:51
Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Goader Thanks for this 👍 Shared a few additional suggestions. Appreciate your advice.

minBaseRevenueContribution: PriceUsdc;

/**
* The fraction of the referrer's base revenue contribution that constitutes their potential award.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* The fraction of the referrer's base revenue contribution that constitutes their potential award.
* The fraction of the referrer's base revenue contribution that constitutes their max potential award. This is the max that ignores the possibility of the award pool becoming exhausted.

@@ -60,14 +60,14 @@ export interface ReferralProgramRulesRevShareLimit extends BaseReferralProgramRu
/**
* The minimum base revenue contribution required for a referrer to qualify.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* The minimum base revenue contribution required for a referrer to qualify.
* The minimum base revenue contribution required for a referrer to qualify for awards.

@@ -60,14 +60,14 @@ export interface ReferralProgramRulesRevShareLimit extends BaseReferralProgramRu
/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggest we also rename totalAwardPoolValue to just awardPool.

@@ -60,14 +60,14 @@ export interface ReferralProgramRulesRevShareLimit extends BaseReferralProgramRu
/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since we're already making a number of breaking changes in this PR, what do you think about changing BASE_REVENUE_CONTRIBUTION_PER_YEAR so that it stops being a hardcoded constant and instead becomes another variable inside the rules here. For example it might be called something like baseAnnualRevenueContribution.

@@ -159,12 +159,12 @@ export const buildRankedReferrerMetricsRevShareLimit = (
export interface AwardedReferrerMetricsRevShareLimit extends RankedReferrerMetricsRevShareLimit {
/**
* The standard (uncapped) USDC award value for this referrer, computed as
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* The standard (uncapped) USDC award value for this referrer, computed as
* The uncapped USDC award value for this referrer, computed as


// 3. Sort referrers to assign ranks:
// 1. qualifiedAwardValue (awardPoolApproxValue) desc — actual pool claims, race winners first
// 1. qualifiedAwardValue (cappedAwardValue) desc — actual pool claims, race winners first
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggest we also refine the name given to qualifiedAwardValue and qualifiedAwardValueAmount and any other fields we can refine to more consistently name ideas across all of this logic.

rules.qualifiedRevenueShare,
rules.maxBaseRevenueShare,
).amount;
const claimAmount =
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe nice to use min here?

@@ -162,7 +162,7 @@ export const buildReferrerLeaderboardRevShareLimit = (
BigInt(SECONDS_PER_YEAR);
const incrementalStandardAwardAmount = scalePrice(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
const incrementalStandardAwardAmount = scalePrice(
const incrementalUncappedAward = scalePrice(

rules.qualifiedRevenueShare,
rules.maxBaseRevenueShare,
).amount;
const claimAmount =
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
const claimAmount =
const incrementalCappedAward =

console.log(`Max Base Revenue Share: ${leaderboardPage.rules.maxBaseRevenueShare}`);
console.log(
`Tentative award for the best referrer: ${firstReferrer !== null ? firstReferrer.awardPoolApproxValue : noReferrersFallback}`,
`Tentative award for the best referrer: ${firstReferrer !== null ? firstReferrer.cappedAwardValue : noReferrersFallback}`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
`Tentative award for the best referrer: ${firstReferrer !== null ? firstReferrer.cappedAwardValue : noReferrersFallback}`,
`Tentative award for the top ranked referrer: ${firstReferrer !== null ? firstReferrer.cappedAwardValue : noReferrersFallback}`,

Copilot AI review requested due to automatic review settings April 7, 2026 15:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.test.ts:342

  • The scenario heading and inline comments still refer to "standard"/"qualifiedAward" terminology, but the implementation now ranks by cappedAwardValue (pool-claimed) and exposes uncappedAwardValue. Please update this test name/comments to use the current field names so the ranking criteria is accurately documented.
  describe("Ranking", () => {
    it("ranks referrers by qualifiedAwardValue desc, then uncappedAwardValue desc", () => {
      // Pool = $1000 (unlimited for this test)
      // ADDR_A: 1 year → qualifies at t=1000, qualifiedAward = $2.50, standardAward = $2.50
      // ADDR_B: 2 years → qualifies at t=2000, qualifiedAward = $5.00, standardAward = $5.00
      // ADDR_C: 0.5 years → never qualifies, qualifiedAward = $0, standardAward = $1.25
      const rules = buildTestRules();

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* - qualifiedRevenueShare = 0.5
* - baseAnnualRevenueContribution = $5 USDC
* - maxBaseRevenueShare = 0.5
* - 1 year of duration → $5 base revenue → $2.50 standard award
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This doc comment still describes the computed value as a "standard award", but the code/API now calls this uncappedAwardValue (and the pool-claimed value cappedAwardValue). Please update the terminology here to match the renamed fields to avoid confusion.

Suggested change
* - 1 year of duration $5 base revenue $2.50 standard award
* - 1 year of duration $5 base revenue $2.50 uncappedAwardValue

Copilot uses AI. Check for mistakes.

describe("Scenario A — unqualified referrer: no award claimed", () => {
it("accumulates standard award but awardPoolApproxValue is $0 when not qualified", () => {
it("accumulates standard award but cappedAwardValue is $0 when not qualified", () => {
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Test description says "accumulates standard award" but the asserted field is uncappedAwardValue. For consistency with the renamed fields, update the test name/description to refer to the "uncapped" award here.

Suggested change
it("accumulates standard award but cappedAwardValue is $0 when not qualified", () => {
it("accumulates uncapped award but cappedAwardValue is $0 when not qualified", () => {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts (1)

188-219: 🧹 Nitpick | 🔵 Trivial

Consider validating the uncappedAwardValue formula.

The validator parses uncappedAwardValue as a generic PriceUsdc but does not verify it equals maxBaseRevenueShare × totalBaseRevenueContribution. A caller could pass an arbitrary value that still satisfies cappedAwardValue <= uncappedAwardValue, weakening the field's documented contract.

If the formula should be enforced at validation time, compute the expected value from rules.maxBaseRevenueShare and metrics.totalBaseRevenueContribution and assert equality. Alternatively, if this is intentional (e.g., to allow flexibility for future use cases), document that the formula is not enforced here.

♻️ Suggested validation addition
   makePriceUsdcSchema("AwardedReferrerMetricsRevShareLimit.uncappedAwardValue").parse(
     metrics.uncappedAwardValue,
   );

+  // Validate uncappedAwardValue matches the documented formula
+  const expectedUncappedAmount =
+    (BigInt(Math.floor(rules.maxBaseRevenueShare * 1e18)) *
+      metrics.totalBaseRevenueContribution.amount) /
+    BigInt(1e18);
+  if (metrics.uncappedAwardValue.amount !== expectedUncappedAmount) {
+    throw new Error(
+      `AwardedReferrerMetricsRevShareLimit: uncappedAwardValue.amount ${metrics.uncappedAwardValue.amount.toString()} does not match expected ${expectedUncappedAmount.toString()} (maxBaseRevenueShare × totalBaseRevenueContribution).`,
+    );
+  }
+
   makePriceUsdcSchema("AwardedReferrerMetricsRevShareLimit.cappedAwardValue").parse(

Note: The exact arithmetic for converting maxBaseRevenueShare (a number) to work with bigint amounts depends on your decimal precision conventions. Adjust scaling as appropriate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts` around
lines 188 - 219, The validator currently parses metrics.uncappedAwardValue with
makePriceUsdcSchema but doesn't assert it equals the product maxBaseRevenueShare
× totalBaseRevenueContribution; add a check in the
AwardedReferrerMetricsRevShareLimit validation that computes the expected
uncapped amount from rules.maxBaseRevenueShare and
metrics.totalBaseRevenueContribution (apply your project's decimal/scale
conversion to convert maxBaseRevenueShare into the same bigint units), then
throw an Error if metrics.uncappedAwardValue.amount !== expectedAmount; keep
this check adjacent to the existing validations that reference
metrics.uncappedAwardValue and metrics.totalBaseRevenueContribution so it is
clear and consistently enforced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts`:
- Around line 188-219: The validator currently parses metrics.uncappedAwardValue
with makePriceUsdcSchema but doesn't assert it equals the product
maxBaseRevenueShare × totalBaseRevenueContribution; add a check in the
AwardedReferrerMetricsRevShareLimit validation that computes the expected
uncapped amount from rules.maxBaseRevenueShare and
metrics.totalBaseRevenueContribution (apply your project's decimal/scale
conversion to convert maxBaseRevenueShare into the same bigint units), then
throw an Error if metrics.uncappedAwardValue.amount !== expectedAmount; keep
this check adjacent to the existing validations that reference
metrics.uncappedAwardValue and metrics.totalBaseRevenueContribution so it is
clear and consistently enforced.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f1baee5d-d32b-4c01-91a8-a475c2d0c664

📥 Commits

Reviewing files that changed from the base of the PR and between fb767c2 and 5b08c84.

📒 Files selected for processing (18)
  • .changeset/bright-foxes-dance.md
  • apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/mocks-v1.ts
  • packages/ens-referrals/README.md
  • packages/ens-referrals/src/v1/api/zod-schemas.test.ts
  • packages/ens-referrals/src/v1/award-models/pie-split/api/serialize.ts
  • packages/ens-referrals/src/v1/award-models/pie-split/api/serialized-types.ts
  • packages/ens-referrals/src/v1/award-models/pie-split/api/zod-schemas.ts
  • packages/ens-referrals/src/v1/award-models/pie-split/metrics.ts
  • packages/ens-referrals/src/v1/award-models/pie-split/rules.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialize.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/serialized-types.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.test.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts
  • packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts
  • packages/ens-referrals/src/v1/edition-defaults.ts
  • packages/ens-referrals/src/v1/leaderboard-page.test.ts

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.

Refine rev-share-limit variable names

3 participants