Skip to content

Provide detailed referral award accounting #1797

@lightwalker-eth

Description

@lightwalker-eth

Background

  1. See "Feedback 4" in this document.
  2. Each time a referral program edition ends, we want to produce a report to the ENS DAO and the broader ENS ecosystem for how the awards were calculated and distributed. This was manually completed for ENS Holiday Awards (and the pie-split award model) here: https://discuss.ens.domains/t/ens-holiday-awards-referral-program/21675/13?u=lightwalker.eth where we linked to this Google Sheet: https://docs.google.com/spreadsheets/d/1pFWMwScAaxCJngh5Duw8mGskkUC-gxqQX_c6D5zPXVA/edit?gid=0#gid=0
  3. In the rules for the April 2026 edition of the ENS Referral Program, we commit to distributing awards "No later than 15 days after the Edition Period ends." which translates into May 15, 2026. We therefore should ensure we can fully ship this feature by no later than Friday, May 8 to give us time to deploy it, complete a full backfill indexing, analyze the results, and prepare the results for publishing to the ENS DAO and the ENS Ecosystem.

Goals

  1. Update our award calculation logic so that it builds a detailed accounting for how all awards for a rev-share-cap referral program edition are incrementally calculated. This detailed accounting should be generated for each incremental referral that takes place during a rev-share-cap edition.
    1. The data for this detailed accounting should built incrementally in memory within ENSApi (and continuously held in memory within ENSApi), such that it can be referenced when requested to:
      1. Generate a complete accounting of all referrals in a rev-share-cap edition as a .csv file.
      2. Provide detailed accounting for each of the referrals returned on the "referral live feed" or on a page such as the ENS Advocate Detail pages that show details of the referrals made by a specific referrer.
  2. Update the response data model of the new "Referrals" API so that it would:
    1. Include detailed accounting information for each referral that is returned.
    2. NOTE: The expanded set of fields should only concern themselves with rev-share-cap award models. We don't want to invest time and effort now in building these features for the old pie-split award models. For referrals associated with the old pie-split award models it's fine if we don't provide detailed accounting for them.
  3. Create a new API (maybe something like: /v1/ensanalytics/accounting?edition={slug} that returns the complete accounting of all referrals in a rev-share-cap edition as a .csv file.
    1. NOTE: This should only support rev-share-cap editions. If the slug for an edition with a different rule set is provided then this API should return an invalid request error.

Suggested implementation strategy

  1. Update the new "Referrals" API so that the response data model would include an additional attributedEdition field in each record returned in the response. This additional field should either be null (indicating that the referral was not attributed to any referral program edition) or a ReferralProgramEditionAttribution object.
  2. The new ReferralProgramEditionAttribution object might include a data model such as the following fields:
    1. awardModel, identifying the award model of the associated referral program edition.
    2. slug, identifying the slug of the associated referral program edition.
    3. displayName, identifying the display name of the associated referral program edition.
  3. The new ReferralProgramEditionAttribution type could be a type union that is polymorphic based on the awardModel field.
    1. For the case that the awardModel is pie-split then I think we don't add any additional fields to the object because the formulas for pie-split are pretty complicated and we don't want to add scope to our goals here for award models from the past that we probably won't use again in the future.
    2. For the case that the awardModel is rev-share-cap, then we might add a tentativeAward field to the object of type TentativeReferralAwardRevShareCap.
  4. The data model for TentativeReferralAwardRevShareCap might have fields such as the following:
    1. incrementalRevenueContribution: identifying the incremental PriceEth we calculate for this individual referral.
    2. accumulatedRevenueContribution: identifying the accumulated PriceEth we've calculated for the referrer while processing all of their incremental referrals for the edition up through this individual referral (includes incrementalRevenueContribution).
    3. incrementalBaseRevenueContribution: identifying the incremental PriceUsdc amount we calculate for this individual referral.
    4. accumulatedBaseRevenueContribution: identifying the accumulated PriceUsdc amount we've calculated for the referrer while processing all of their incremental referrals for the edition up through this individual referral (includes incrementalBaseRevenueContribution).
    5. awardPoolRemaining: identifying the PriceUsdc amount of the award pool that was remaining before this individual referral.
    6. disqualified: A boolean identifying if the referral was disqualified.
    7. disqualificationReason: An optional string field identifying the reason why the referral was disqualified. This would be the same string value configured in the admin actions. This field should be defined if and only if disqualified is true.
    8. maxRevShare: identifying the max rev share as specified in the rules for the edition.
    9. effectiveBaseRevShare: identifying the effective base rev share as determined by the relationship between incrementalBaseRevenueContribution and incrementalTentativeAward.
    10. incrementalTentativeAward: identifying the incremental PriceUsdc amount tentatively awarded to the referrer for this referral taking into consideration factors such as disqualified, awardPoolRemaining, accumulatedRevenueContribution and possibilities such as:
      1. accumulatedRevenueContribution hasn't passed the minimum yet.
      2. accumulatedRevenueContribution has just now passed the minimum.
      3. The referrer is disqualified.
      4. The award pool was already fully exhausted.
      5. The award pool was not already fully exhausted, but the remaining award pool was not enough to fully pay out the "normal" award for the referral and therefore was truncated to the remaining award pool
  5. Add a new API endpoint to the referrals API that takes as input a referral program edition slug and then outputs a .csv file providing a detailed accounting of all referrals under that edition.
    1. Note: For now we aren't going to promote the existence of API anywhere. Operationally the plan is that we will use this API ourselves to generate a .csv file and then we will convert that .csv file into a Google Sheet which we would then make public and share with the ENS Ecosystem and the ENS DAO so that we will have shared a full accounting of the award calculations for an edition. Support for this API should NOT be added to the EnsReferralsClient.
    2. This .csv file should output all referrals for the requested edition in the order they were executed onchain.
    3. The following columns should be added to the .csv file:
      1. timestamp (output in a human-readable format, not as unix timestamps)
      2. name (identify the name that was registered or renewed)
        1. You shouldn't need to worry about escaping these strings when outputting into .csv because our indexed data model guarantees the values you have for these names are all InterpretedName. All labels are therefore either ENS normalized labels or encoded labelhashes. ENS normalized labels are guaranteed not to include a comma character, and encoded labelhashes don't include commas either.
      3. action (identify if it was a registration or renewal)
      4. transaction hash of the referral
      5. incremental duration of the referral
      6. the registrant
      7. the referrer
      8. ... all the info described above in the detailed accounting data model
      9. ... anything else you think is important for a detailed accounting.

Metadata

Metadata

Assignees

Labels

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions